--- name: "day001" title: "Setting Up the Windows Build" markers: "46": "Course of the Handmade Hero series" "184": "Start the project" "306": "Command line in Windows" "424": "Create a virtual drive" "618": "Meaning of the misc folder" "706": "Create the first code file" "768": "Comment header Emacs put in" "877": "Minimum code you will need" "1185": "Configure everything for development" "2920": "Debug with Visual Studio" "3180": "Windows-specific things you should know" "3544": "Add something to do for the program" "3720": "Import a library" --- name: "day001qa" title: "Setting Up the Windows Build - Q&A" markers: "35": "Could you show how you added the Handmade Hero directory to the path?" "224": "Do all Windows programs written in C/C++ use WinMain? Does The Witness have the same started code?" "288": "What is the difference between Microsoft's compiler and gcc?" "387": "What type of milk are you drinking?" "393": "How do you write a renderer that is hardware accelerated?" "406": "Can we get your .emacs file? Do you always code without line numbers?" "419": "Will there be a sushi bar in Handmade Hero?" "423": "*Question regarding the linker and IDE*" "496": "Is there a reason you didn't use the developer command line shortcuts?" "561": "How much experience do you have audio processing code?" "573": "*Asking whether we'll be setting up things in the Mac OS and Linux environment as well*" "585": "Will it be a 2D or 3D game?" "626": "2-hour streams?" "637": "What style of game are you making? ETA for the game?" "668": "Will the game be Windows-only?" "690": "Will you do extended live streams?" "716": "Can you show the command line parameters that you set in the shortcut?" "805": "What is your favorite Linux distro?" "832": "Will I be able to follow you just using VS 2013 Community Edition?" "904": "Will the game have multiplayer?" "962": "Can you please remove the parentheses in return(0);" "971": "When can we get some details on the actual game?" "991": "Why don't you just compile directly in Visual Studio?" "1046": "How does it feel having more than 700 viewers on the stream?" "1158": "*Question regarding command line and the visual debugger*" "1289": "What GDB frontend do you use on Linux?" "1295": "What did yo uwork on while working on Bink video?" "1440": "Will you look at the chat for viewer answers while you work?" "1447": "*Request to do 5-hour streams*" "1512": "Is there a design document?" "1597": "Are we able to open source our own implementations?" "1643": "Fixed point or floating point For the audio representation in the game?" "1650": "*Comment about the C/C++ specification*" "1681": "Are you staying on Windows for the bulk of the show?" "1771": "Do you have *everything* planned?" "1800": "Why don't you run Windows 8.1?" "1878": "*Comment that mentions the Doom 3 source code*" "1891": "*Comment about getting an intern*" "1920": "*Question regarding Twitch quality settings*" "1947": "Any chance you could stream earlier?" "2005": "Will you have an actual repo for the project?" "2033": "Which better-debugger Linux projects are you looking forward to?" "2057": "Windows 7 doesn't support AVX2." "2082": "*Question regarding repo again (answered in 33:25)*" "2104": "Did you consider doing a Kickstarter for this series?" "2263": "*Remark about Twitch stream quality*" "2275": "*Almond milk powerup confirmed*" "2295": "*Setting up a poll to decide best time to stream on Fridays*" "2320": "What do you think about learning math concepts on Wikipedia?" "2365": "*C++ interfacint with API that deals with a dedicated graphics card*" "2380": "*We are all excited that you're doing this in C*" "2411": "*Another Kickstarter comment*" "2446": "*Remark about having a 3D sequel*" "2516": "Would you consider dropping the framerate/" "2536": "*Wrist glove powerup NOT confirmed*" "2550": "Could you recommend some good books? Tutorials?" "2615": "*Clearing up confusion with C++ structs (related: 52:35)*" "2744": "*How we'll transition to take advantage of hardware acceleration*" "2770": "Can you make constructors in C++ structs?" "2789": "*Yet another Kickstarter comment*" "2852": "Are you planning to have descriptive names for the Youtube archive videos?" "2880": "*30 FPS game confirmed*" "2893": "What's up with the Handmade Hero icon on the Twitch page?" "2904": "*Benefits of learning things from scratch*" "3030": "#milkhit" "3035": "Will you ditch the #include ?" "3044": "How often do you use the debugger?" "3062": "Why do you scope the for-loop the way you do? (Muratori For Syntax)" "3091": "*Micro-transactions are all the rage. Suggestion to use them*" "3140": "Will there be an option to pre-order as a gift for a friend?" "3155": "*Difference between C and C++ structs*" "3192": "*Suggestion on putting a green screen behind Casey*" "3201": "Will sound effects be implemented right away?" "3226": "*Twitch partnership is a possibility (?)*" "3246": "How do you plan to design a good game?" "3410": "Why start from scratch?" "3730": "Set up an official forum?" "3842": "Why not code in just pure C or pure C++?" "3990": "Is there a game dev company you really admire?" "4097": "Where do most of your audience come from?" "4228": "SDL or SFML?" "4254": "*Closing Remarks*" --- name: "day002" title: "Opening a Win32 Window" markers: "200": "WNDCLASS Implementation start" "280": "Struct explanation of why Windows Documentation is the way it is" "578": "Initialization of WNDCLASS" "1317": "CALLBACK explanation and basic implementation" "2201": "Registering the WindowClass" "2330": "CreateWindowEx()" "2650": "Windows Message queue | GetMessage()" "3060": "Drawing something with WM_PAINT" "3420": "Switching between drawing BLACKNESS and WHITENESS" --- name: "day002qa" title: "Opening a Win32 Window - Q&A" markers: "92": "Question about Atoms in Windows API" "137": "Can you go fullscreen?" "160": "Improving the way things are shown on stream" "182": "What's the fastest path for getting a pixel on the screen on Windows?" "285": "Dealing with ANSI strings" "369": "Do you use always the same technique for creating a fullscreen window?" "398": "Is the for-loop just for keeping the window alive?" "506": "Can I preorder the Epilepsy Simulator?" "528": "Do we want the player to resize our window?" "549": "Can you experiment what happens when you take out CS_HREDRAW and CS_VREDRAW?" "631": "Any considerations for 64-bit on tonight's code?" "822": "Using const qualifier" "895": "Compilation issue" "1043": "You're nesting quite a lot of blocks." "1084": "My app doesn't respond to the window's close button" "1215": "for(;;) vs. while(true)" "1349": "Can you explain the Window Handler one more time?" "2027": "Closing remarks" --- name: "day003" title: "Allocating a Back Buffer" markers: "50": "Short overview about a backbuffer" "176": "Windows message callback" "283": "Closing the window (PostQuitMessage function)" "550": "about resource handling" "766": "Back to closing the window" "956": "about global variables" "1020": "Different meanings of static: internal, global_variable, local_persist" "1367": "Backbuffer, windows, GDI and us." "1409": "resizeDIBSection() created" "1566": "GetClientRect()" "1849": "CreateDIBSection() created" "1899": "StretchDIBits()" "2311": "CreateDIBSection() usage and explanation" "2899": "About freeing and creating a new DIBSection" "3222": "Device context and Win32ResizeDIBSection()" "3803": "Q&A" "3817": "Remark on not needing to use CreateDIBSection/CreateCompatibleDC and just allocating the array ourselves" "4007": "Remark on the change to the archiving of Q&A sessions (they are now combined with the main day video)" "4117": "Will you be using sleep()?" "4139": "Could you go back through how you got Visual Studio to cooperate?" "4192": "Are other windowing systems less crazy to work with?" "4340": "Are you going to do a more detailed Intro To C series alongside this one?" "4420": "Can you explain what exactly a void* is? A pointer to nothing?" "4803": "Any new thoughts on IMGUI since you made that video a few years ago?" "4875": "Follow up on the previous remark about StretchDIBits, it can take a custom array as long as it is DWORD aligned" "4993": "When will the source be available?" "5010": "When using emacs, I find it hard to use meta key with F and B to skip words, how do you do it so fast?" "5028": "How come !=0 is true in C, and return values of main and functions is 0 if everything is okay?" "5178": "Remark on functions with multiple return values "Pre ANSI C didn't allow return structs"" "5304": "Any reason you put the type in a line above the function name?" --- name: "day004" title: "Animating the Back Buffer" markers: "30": "Correction about StretchDIBits()/BitBlt()" "320": "Writing our custom BitmapMemory allocator. (Note about aligned/unaligned byte access)" "433": "Basic math to determine the bytes needed for BitmapMemorySize. 'Width * Height * BytesPerPixel'" "477": "Description and usage of VirtualAlloc(), the WIN32 memory allocation function we will be using" "795": "Making sure we free any allocated memory before we resize, using VirtualFree()" "920": "Aside about VirtualProtect(), useful to prevent stale pointers and "use after free" bugs" "1009": "Step through of Win32ResizeDIBSection()" "1065": "Changing Win32UpdateWindow() to use BitmapMemory" "1170": "Adding Bitmap dimensions as global variables (temporarily)" "1200": "Setting Bitmap Width/Height and using them in Win32ResizeDIBSection()" "1220": "Setting Window Width/Height in Win32UpdateWindow()" "1317": "Notes on storing a 2D image inside a 1D "block" of memory. Pitch/Stride." "1470": "Setting biHeight to a negative number to ensure the window framebuffer uses a top-down coordinate system with its origin in the top left corner" "1559": "Note on getting MSVC to give full paths to files in the build output log. (Add -FC to build.bat) Allows emacs to jump between build errors" "1620": "BUGFIX: Win32UpdateWindow() definition change" "1665": "Drawing pixels into the bitmap" "1745": "Adding typedefs for specific type sizes" "1839": "Casting void* to different size types to make pointer arithmetic simpler for bitmap access" "2016": "Pixel component layout in memory on Win32. Flipped to read RGB when viewed in the memory registers." "2290": "Drawing pixel colors based on the X and Y" "2410": "Moving bitmap rendering into RenderWeirdGradient()" "2560": "Adding animation and switching GetMessageA() for PeekMessage() so that Windows doesn't block" "2723": "Making sure we handle WM_QUIT inside our PeekMessage() loop" "2783": "Adding XOffset/YOffset variables to the main loop, ++1 them each time through the loop" "2860": "BUGFIX: Adding our window blitting function (Win32UpdateWindow()) to the main loop, so the bitmap will blit each time through the loop" "3025": "Changing "WindowHandle" to "Window" and "WindowRect" to "ClientRect"" "3116": "FINALLY ANIMATION!" "3265": "Changing DrawWeirdGradient() to use a 32-bit pointer and write each pixel in one call using bitwise operations" "3518": "Verification of lack of memory leaks" "3584": "TOTAL SYSTEM MELTDOWN" "3727": "Q&A" "3730": "Is there a reason you prefer using 0 instead of NULL?" "3798": "Clarification about sized typedefs" "3898": "What would happen if you called malloc() instead of VirtualAlloc()?" "3932": "What's the difference between malloc and new and HeapAlloc()?" "3987": "Do you think you could go as slow as you did previous days in the future?" "4047": "Are we going to use Valgrind in the future?" "4063": "Is the project going to take 2 years?" "4090": "Can you explain why we are using the user32.lib and gdi.lib in the build.bat?" "4122": "Would there be a significant performance increase if we allocated the memory for the bitmap on the stack instead of the heap?" "4227": "Do you know what the PAGE_WRITECOPY Memory Protection flag does?" "4552": "About bytes per pixel and bitmap memory layout. Pitch/Stride. Pitch is byte offset between rows." "4789": "You mentioned xxBBGGRR because of little endian, why was the blue channel set in this case instead of the padding?" "4890": "Could the padding byte be used as an alpha channel here?" "4926": "Why are we having a wait symbol on the window?" "4970": "Could you explain the offset to X and Y?" "5040": "About the global_variables and the static keyword" "5295": "Static doesn't give you zero on initialization?" "5378": "Do you consider overflowing numbers to be a good coding practice?" "5423": "Note about statics and extern global variables being initialized to zero" --- name: "day005" title: "Windows Graphics Review" markers: "69": "Brief overview of the week's work." "133": "Capture card considered unneccesary?" "187": "Value of HREDRAW and VREDRAW" "288": "Helping the compiler optimize by avoiding unnecessary pointers" "390": "Explanation of pointer aliasing" "704": "What difference does it make if I put a declaration inside a loop instead of outside it?" "1110": "Where to get Liberation Mono, the font Casey uses." "1174": "Dealing with global variables more cleanly by bundling them up into structures" "1738": "Making a global backbuffer" "1799": "Explanation of Access Violations" "1996": "Aside about types of errors you find in code" "2232": "GetWindowDimension() created" "2462": "Why keep using Width/Height instead of win32_window_dimension?" "2618": "Changing the backbuffer to be fixed size" "2837": "Full step-through with in-depth analyis of program behavior" "3164": "Deep dive on the size of the stack" "3350": "STACK OVERFLOW ACHIEVED" "3705": "Step-through resumed" "5015": "Q&A" "5046": "Would it be a good or bad idea to get one DeviceContext at the beginning of the program and use that for every iteration of the main loop?" "5166": "Chihuahua on speed confirmed" "5182": "Why do you tell Windows you handle messages you don't really handle?" "5346": "I believe SetStretchBltMode() will allow you to get better quality stretching." "5380": "Can you please explain pointer aliasing again?" "6347": "Owl of Shame Moment: Pointer aliasing explanation fail" "6566": "Proper pointer aliasing explanation" "7042": "I was under the impression that the stack always grows downwards on little endian architectures, is that not true?" "7090": "Can you post interesting e-mails you get to the site?" "7111": "The compiler is allowed to, and actually does, assume that two pointers to different types never alias unless one of the types is char or unsigned char" "7186": "Win32DisplayBufferInWindow() is taking four unused parameters. WM_PAINT is the only part where we pass those, but we never use them. Will that change?" "7262": "Wouldn't it be better to keep comments in the code about the explanations you do?" "7287": "Why have BytesPerPixel as a variable? Do you expect it to have different values?" "7384": "On the uselessness of const" --- name: "day006" title: "Gamepad and Keyboard Input" markers: "51": "Getting input from a gamepad: XInput" "200": "Using XInput in the codebase" "386": "A look at the XInput API more in depth." "460": "Programming using XInput API" "549": "Discussing the controller's state: using XINPUT_STATE struct" "690": "Using XINPUT_GAMEPAD struct" "1017": "Handling unresolved external symbol XInputGetState" "1563": "Discussing access violations" "1612": "Safeguarding against access violations" "1910": "Defining and implementing Win32LoadXinput function" "2242": "Playing with the X and Y offset" "2280": "Casey looking for his gamepad" "2330": "Casey showcases pink controller" "2469": "XINPUT_VIBRATION" "2585": "#milkhit" "2815": "Testingand handling button/key presses" "3310": "(Extra) ANSI String Handling" "3370": "(Extra) Not passing something by value anymore" "3490": "Summary and things to come before beginning Q&A" "3548": "LParam 30 is always up for WM_KEYUP" "3597": "Why uppercase variable names?" "3621": "Can you explain your macro and referencing XInput functions again?" "3795": "What's the size when copying becomes problematic for a struct?" "3867": "About (premature) optimisation" "4107": "How does the linker find the XInput DLL on the users machine? [...] Can we distribute the DLL?" "4372": "Is [the dynamic linker] allowed to link XInput in compile time?" "4442": "Why you chose an if-else cascade for key input instead of switch statement? It's up for grabs." "4513": "How do you know the XInput stub things work without testing it on XP computer without XInput installed?" "4623": "Is it a waste of time to check if GetProcAddress() returns zero?" "4752": "Modify code to use the controller stick" "4934": "Where do the WParam and LParam come from?" "5057": "Why did MS decide to use link and import library instead of true dynamic linking?" "5113": "When are we going to get naysayer88 and cmuratori combination game?" "5179": "On Unix you don't need to link to a .so file at all to use a .so file where as on MS platforms you need a .lib file" "5253": "In the far future will you use DirectX or OpenGL or what?" "5285": "We will be drawing the whole screen every frame." "5327": "Why does Valgrind make it look so scary when you don't free()?" "5388": "It looks like WParam and LParam are 32bit on XP" "5412": "Is it possible to keep your framerate consistent while dragging the window around? Doing repaint on WM_MOVE is slow." --- name: "day007" title: "Initializing DirectSound" markers: "53": "Fix: Windows API return values and stubs" "149": "Fix: XInput on Windows 8" "228": "Fix: Restore Alt-F4 functionality" "561": "Bool datatype idiosyncraries" "775": "Review Alt-F4 fix" "835": "Foreshadowing an XInput performance issue" "1004": "Intro to sound programming for games" "1435": "Initializing DirectSound Overview" "1623": "Load the library" "1920": "Create a DirectSound Object" "2034": "Configuring the DirectSound Object" "2284": "Creating and Configuring the Primary Buffer" "3096": "Creating and Configuring the Secondary Buffer" "3398": "Let's try it" "3646": "Final Thoughts" "3725": "Q&A" "3845": "Fixing WaveFormat order" "3967": "Do you use data-structures like linked-list, binary trees..?" "3994": "Can you explain again why you need two buffers instead of just doing everything in one?" "4163": "Are there any case we'd want more than two [audio] channels?" "4265": "If the framerate would ever drop, can there be audio dropouts?" "4421": "The nBlockAlign and nAverageBytesPerSecond are redundant." "4497": "On Linux will we be doing ALSA or higher level like PulseAudio/Jack?" "4560": "What newer sound API would you recommend instead of old DirectSound?" "4606": "The two second buffer doesn't sound acceptable / not-noticeable if you're playing music." "4647": "Have or do you work in the industry?" "4674": "Have you thought about guest programmers tagging in to teach things like linux or whatever topic is their expertise?" "4715": "VirtualAlloc: MEM_COMMIT to MEM_RESERVE|MEM_COMMIT" "4823": "About game development as a career field" "4977": "Will you show us how to use bone animations or will you use spritesheets?" "5055": "More on our usage of DirectSound (Not a buffer)" "5133": "About game programming optimisation" "5276": "Why don't we use the second buffer to grab the handle instead of creating something just to grab a handle?" "5366": "Isn't this learning how to carve stone with chisel instead of using modern machinery?" --- name: "day008" title: "Writing a Square Wave to DirectSound" markers: "64": "Review of DirectSound init" "136": "Tangent: methods and vtables" "532": "Resume review of DirectSound init" "861": "Writing to the sound buffer" "969": "Discussion of waveforms for testing" "1022": "Locking the buffer" "1099": "Dealing with buffer pointers and locks" "1269": "The Lock() call" "1379": "Filling the buffer regions" "1609": "Generating a test tone" "2128": "Getting the WritePointer and BytesToWrite" "2901": "Refine square wave formula" "3099": "Review the code" "3364": "Start DirectSound playing" "3447": "HOLD YOUR EARS" "3502": "HOLD YOUR EARS" "3562": "Don't forget to Unlock the buffer" "3658": "Final Thoughts" "3737": "Review of mod operation and how we used it" "4230": "Q&A" "4269": "Will future broacasts use this Europe-friendly time?" "4281": "Why not XAudio2?" "4363": "Are we going to factor sound playing to a seperate function?" "4425": "Will we rename GlobalSecondaryBuffer?" "4450": "Challenge: XAudio2 is supported on XP" "4489": "Why keyboard events instead of polling?" "4524": "Will we be able to remap keys?" "4543": "Doesn't the size of the buffer increase latency?" "4613": "Will we write audio filters, like reverb?" "4636": "Will we factor the code into seperate files?" "4686": "It takes about a second to start playing, is that expected?" "4959": "Can you show a sine wave as well?" "4982": "What is acceptable latency?" "5344": "No Poop Sauce" --- name: "day009" title: "Variable-Pitch Sine Wave Output" markers: "74": "Review DirectSound init and square wave" "148": "Story Time: The First Game Jam" "536": "The moral of the story" "686": "How to approach debugging the sound code" "940": "Square vs Sine Wave" "1053": "Generating a Sine Wave" "1076": "Tangent: Intro to Floating Point" "1238": "C Libraries for sin" "1495": "Story Time: Before floating point hardware" "1603": "Tangent: Fixed-point math" "1955": "Tangent: IEEE Floating-point representation" "2535": "Implementing the Sine wave test tone" "2889": "Lets run it" "2941": "Debugging in earnest" "3459": "A different error" "3478": "Refactor for clarity" "3826": "Where did it go?" "3848": "Eureka!" "3922": "Victory" "4192": "Q&A" "4207": "In D this bug couldn't have happened. D always initializes variables." "4416": "How do you know that ByteToLock is far enough ahead of the PlayCursor?" "4540": "Try [compiling with] -W3 or -W4" "4554": "Where do I look for standard C library docs?" "4599": "I think you can now remove the ByteToLock == PlayCursor case." "4678": "Will we use the sin() in the actual game?" "4687": "Is autocomplete/intellisense a bad idea? You don't seem to use it." "4765": "Re-explaining the last bug" "4850": "Is it possible for bits to spill over into neighboring variables? For example, when shifting." "5186": "Will we use the same output buffer to overlay several sounds?" "5193": "Change tone frequency based on input, and the bug will resurface." "5197": "Casey: That's a different bug, lets look at it." "5443": "Fixed" "5457": "Diagramming the frequency change issue" "5718": "Let's map the pitch to the sticks." "5820": "Theramin Simulator 2014 Tech Demo" "5833": "Let's lower the latency" "6169": "If we could live with a slightly less accurate sin, we could approximate it with polynomials." "6308": "Will the art and audio be released into the public domain?" "6380": "Is it a good idea to use fixed point math for games that require deterministic simulation for multiplayer? Or can you use floating point across systems?" "6528": "Sometimes you use 'bool' and sometimes 'bool32'" "6570": "Are you going to use ETW to log context switches for the game?" "6582": "Is this the audio api we will be using to ship the game?" "6601": "Is it safe to call DirectSound without initializing COM?" "6647": "Can we do an episode on emacs?" "6693": "Fix: XInput - missing dependencies" "6825": "Fix: Arithmetic for stick values" "7315": "Sign off" --- name: "day010" title: "QueryPerformanceCounter and RDTSC" markers: "79": "The Intel Architecture Reference Manual" "229": "RDTSC- Read Time-Stamp Counter, measures clock cycles" "460": "QueryPerformanceCounter(), measures wall clock time" "930": "Timing our frames" "1022": "Union types (LARGE_INTEGER)" "1308": "Method of determining time elapsed between frames" "1399": "QueryPerformanceFrequency()" "1592": "Using dimensional analysis to convert between unit types" "1873": "Converting seconds/frame to ms/frame" "1956": "Printing out MSPerFrame" "2290": "Finding Frames Per Second using dimensional analysis (cause we can)" "2744": "The dangers of wsprintf()" "3010": "Using RDTSC to find cycles per frame" "3403": "Use wsprintf() to print our timings as floats" "3558": "A bit more about wsprintf()" "3725": "Final Thoughts" "3872": "Q&A" "3886": "RDTSC returns unsigned int" "3928": "Explanation of how C handles division based on type" "4054": "How compiler optimizations affect the execution time" "4198": "Do the divide in doubles." "4406": "It would be nice to have a roadmap...Would you consider doing a 24 hour stream?" "4470": "Will we be able to use a Playstation 2 controller?" "4493": "Can we expect more Jeff and Casey shows in the future?" "4504": "Is it safe to use 64-bit variables and functions on a 32-bit PC?" "4577": "Even though we are doing low level programming, sometimes we have to pass things to Windows, which makes it difficult to follow exactly what the computer is doing. Will this be the same when we go to other platforms?" "4725": "Do you use a profiler or mostly hand-coded timing calls?" "4737": "Why do you use PascalCase for everything?" "4744": "Is it a violation to set one member of a union and then read from another?" "4755": " Was wondering when we would get around to using RawInput to handle DualShock 4 natively" "4847": " Modern CPUs RDTSC returns nominal clocks not real clocks." "4934": "Why are you avoiding doubles in your code?" "4970": "Are you opposed to ever using high level languages in making games?" "5003": "If you wanted to lock the FPS at a particular number, would you just sleep or do something more complex?" "5095": "Isn't RDTSC affected by variable processor technologies in modern processors like SpeedStep?" "5214": "Have you done Ludum Dare?" "5230": "Can we do a bonus stream on ASM?" "5331": "If you read the latency tables for SSE2 float vs double, you'll see that double isn't that much slower than float..." "5838": "What are your thoughts on Swift?" "5843": "What do you think of Jonathan Blow's programming language?" "5870": "Do you have any discussions with Jonathan Blow on his compiler and what sort of features you would like to see in it?" "5939": "Do you ever write functions like printf() that take variable arguments?" "5947": "Would you consider using a templated type-safe version of printf(), even though you hate templates?" "5968": "MULPD is only half as fast if you do millions of operations..." "6003": "What low level language would you suggest to someone new to programming?" "6013": "Are we using the Win32 API but compiling for 64-bits? Do we need to compile for 32-bits for Windows XP support? It looks like we have int64 and real64 in the cpp" "6050": "In game development, do you follow enterprise design patterns, or do you have some different design patterns?" "6069": "What do you use for collections if you do not use templates?" "6078": "I didn't get the outome of the MULPS/MULPD compare. The latency packing was the same, how does that end up being double time?" "6244": "RE MULPS/MULPD: If you're writing SIMD code then you care, otherwise you don't." "6358": "Comment about compiler auto-vectorization" "6463": "Tom Forsyth's rant on double precision" "6515": "Will we take MSVC all the way to shipping or will we use LLVM even on Windows?" "6603": "What's an intrinsic?" "6923": "Switch back to debug build from optimized" "6963": "Isn't it a pain to work in Windows, especially as a programmer?" "7025": "Didn't we want to start adding warnings?" --- name: "day011" title: "The Basics of Platform API Design" markers: "215": "About platform specific code" "476": "What is left to be done on the platform layer" "683": "Topic of the day revealed!" "693": "Portability and cross platformness" "817": "How people used to make code be cross platform (preprocessor #if #else)" "1128": "About preprocessor #if #else cross platforming" "1432": "Separate platform files (e.g. linux_handmade.cpp) as the entry point" "1901": "Unity builds, building your project as one translation unit" "2048": "Virtualising the OS to the game (architecture style 1)" "2063": "Example implementation for virtualising a window wrapper" "2574": "Reasons why perhaps not to use style 1" "2671": "Game as a service to the OS (architecture style 2)" "2835": "Implementing style 2" "3090": "GameUpdateAndRender() - moving RenderWeirdGradient to game code" "3660": "Q&A" "3683": "Seems 'unsafe' to include the platform independent code after including the platform specific headers" "3802": "Would you always orchestrate how you do threading in the platform layer or does it make sense for the platform layer to also provide a more generic threading job service?" "3912": "You said last stream you didn't really like showing the FPS because you didn't find it useful. Can you explain that?" "4188": "On the scale from genius to totally awesome how can you remember all this?" "4341": "Do we currently have a hidden platform dependancy inside the bitmap memory or is BGRA something that happens on the other platforms too?" "4518": "It seems like your approach to handling platform dependant services is to prefer a many-to-one relationship instead of a one-to-many. [...]" "4673": "How did you setup Visual Studio to have that black theme?" "4702": "During coding is it easy to discipline yourself to make the code as clean and tidy as possible. [...] Do you think this is good in general or could it backfire?" "4940": "Would there be a way to build your platform dependant code in a separate entity in order to allow you to use it in the future?" "4991": "Will you be developing your own implementation of strings? (No) " "5032": "Does the unity build approach work with parallel compilation?" "5164": "Do you feel it is necessary to make a flowchart before coding, or do you go with the flow?" "5238": "Why the #define part for the header file (include guards)" "5349": "Why do you specify void in function definitions when they don't take arguments?" "5406": "Do you have a specific method for solving programming problems or do you just write things and solve them in place?" "5429": "Why are you forward declaring game layer functions in the header when you include the whole documentation?" "5477": "Do you think it is realistic for someone with awful math skills to be an efficient game developer?" --- name: "day012" title: "Platform-independent Sound Output" markers: "57": "Review basics of platform API design" "234": "What the API needs to support" "293": "Starting with moving sound across the API boundary" "630": "How most games deal with time (poorly)" "666": "What we are going to do" "895": "Moving sound generation across the boundary" "1170": "Finding the seams" "1369": "Dealing with sound buffers abstractly" "1550": "Allocating a game sound buffer" "1773": "Tangent: buffer overruns and how the debugger helps" "1869": "Actually using the game-generated sound" "2221": "Cleaning up the old stuff" "2536": "A step back" "2610": "Tangent: memory management & alloca" "2877": "Nevermind, we'll put it on the heap" "3057": "Review" "3234": "The remaining jank" "3447": "Tweak the build.bat" "3527": "Final Thoughts" "3570": "Q&A" "3616": "Will we use alloca to store pointers to game objects that are local to the player?" "3869": "If the DirectSound Lock fails, you'll pass garbage pointers to the game logic." "3931": "When you say 60fps may not be feasible do you mean on non-PC platforms?" "4070": "Are we not worried about clean builds?" "4117": "Allocating every frame was your bug with alloca. You were calling it in a loop." "4346": "Can you explain again why our current sound buffer fill is problematic?" "4543": "Wouldn't updating graphics and sound on the same frame cause audio lag?" "4628": "Since alloca is just a function call, how does the compiler know to free the memory?" "4664": "Will we spilt game sound update out of GameUpdateAndRender so we can use it as a callback or on a different thread?" "4696": "alloca is deprecated, we should use malloca." "4817": "can you provide a log of the chat on the website?" "4843": "malloca allocs on the stack if less than 1kB and malloc's if greater." "4893": "How can you safely predict where the flip happens so you can write sound there?" "5094": "We know that you can't go below 30fps for 'smooth' video. Is there a similar rule of thumb for audio?" "5189": "alloca is deprecated because.... [There are better options.]" "5449": "How do you do 2 voices in 1 buffer?" "5458": "When will the first sprite be displayed in animation?" "5471": "I've heard the brain treats sounds within 10ms as in-sync?" "5499": "When you work with temporary memory are there dangers? How do we protect against them?" "5601": "As a rhythm game player, I can notice audio sync off as little as 10ms..." "5703": "Sign Off" --- name: "day013" title: "Platform-independent User Input" markers: "40": "Overview of the day's goals" "155": "Function Overloading (accidental and intentional)" "449": "Extending GameUpdateAndRender() to take input" "513": "Pulling structs into a header file for readability" "588": "On iterating towards an API and avoiding premature design" "815": "Writing our usage code first" "912": "Diagram of input over time" "1247": "Looking at one common method of parsing game input" "1423": "An less expressive but simpler way" "1709": "But Casey, what about the stick?" "2147": "Writing usage for some game_input structures" "2271": "Adding the structures and filling them out" "2445": "Handmade Hero: Better than cooking shows!" "2534": "Porting our platform layer over to the new API" "2776": "Factoring out button processing into Win32ProcessXInputDigitalButton()" "2927": "Processing all the buttons" "3071": "ArrayCount() used but not implemented yet" "3196": "Swapping NewInput and OldInput, how do we want to do it?" "3276": "Finally defining NewInput and OldInput" "3364": "More explanation about swapping" "3448": "Defining the ArrayCount() macro" "3530": "But Casey, what about the stick?" "3611": "Normalizing our stick values" "3894": "Wrap up and Final Thoughts" "4015": "Q&A" "4025": "When normalizing the thumbstick value, is it worse to just add 32768 then multiply it by 2/65535 then subtract 1? I don't like the necessary if statement personally." "4125": "Nitpick, but is it a bit misleading that the half transition count is zero or one, rather than an actual count?" "4157": "Will we be completely ignoring platform code for most of the rest of the series?" "4188": "Can you describe the struct inside of the union in more detail?" "4417": "Does it give any problems with capturing inputs over time when, due to some circumstances from Windows, the game lags and the frame timebase expands?" "4563": "Your normalizing code has an error, they both divide by positive." "4673": "What happens if there's a name conflict between struct scope and a non-nested struct?" "4715": "Do you plan on abstracting the input more. For example, instead of having a player respond to a button press, have them respond to an action that is bound to a button or stick?" "4801": "Why is GameUpdateAndRender() internal when it's designed to be called from the platform layer?" "4835": "Comment about using re-bindable keys and buttons for left-handed people." "4877": "When will you decide to actually remove all the TODOs in your code?" "4911": "Aside about rebindable keys." "4981": "How is the old controller persisted across frames?" "5039": "Will the Windows callbacks for keyboard inputs require a great deal of extra work for you to implement?" "5118": "What about people who only have left arms?" "5145": "Will we eventually be using a timer to poll the controller input, or just a thread?" "5200": "timeBeginPeriod(1) will tick at 1 millisecond resolution." "5257": "Have you done much physics coding, related to games or otherwise?" "5305": "Would you be fine with people using the platform as a base for making their own games, with attribution?" "5389": "How much will you need to explore other platforms before knowing what the abstraction API will look like?" "5426": "What kinds of numerical methods are used in game physics?" "5486": "Final Wrap Up" --- name: "day014" title: "Platform-independent Game Memory" markers: "58": "Intro to memory management." "247": "We won't be allocating." "317": "'Allocation Festivals'" "335": "Why talk about allocation now?" "455": "What would 'normally' happen" "715": "Problem: dynamic allocation spreads managment across code, makes it opaque" "798": "Problem: allocation is another trip through the platform layer" "903": "What we will do instead" "1045": "Adding memory to the platform abstraction" "1241": "Initializing with the new model" "1277": "Allocating the memory in the platform" "1593": "Yes, Virginia, memory comes zeroed." "1720": "Put it where you want it." "2013": "Debugging: Integral promotion" "2198": "Note that the clear to zero is cheap." "2247": "Memory? Check." "2428": "Intro to assertions" "2673": "Avoiding the runtime cost" "2703": "Build options" "2888": "Build options for memory" "3031": "Combining allocations" "3090": "Debugging" "3307": "Mission accomplished." "3384": "TODO: Pass timing info to game" "3504": "Q&A" "3560": "Reasoning behind Main Memory Pool vs Dynamic Allocation?" "3811": "Why use the void* in game_memory?" "3853": "Elaborate on Permanent vs Transient storage?" "4023": "Will the code be on github [be public]?" "4058": "What do you mean by 'avoiding round trips'?" "4375": "Are you going to keep the sound buffer allocation seperate?" "4394": "Why didn't you use libc's assert macro?" "4423": "You're assert has issues." "4477": "Why did you pick a BaseAddress so high up (2TB)?" "4509": "What is the difference between the memory columns in Task Manager?" "4661": "Tangent: PerfMon" "4839": "Recommended: Channel 9 video: Mark Russinovich Mysteries of Windows Memory Managment." "4864": "Are there any guidelines for choosing a safe BaseAddress?" "4906": "What happens if the user doesn't have enough RAM?" "4960": "Isn't worrying about not having enough memory silly?" "5005": "Why are you using pools instead of static allocation?" "5032": "What mechanism will we use to assign memory out of our pools?" "5057": "Having Q&A after the episode is like code review. Was that your intent?" "5116": "What about i.e. modding support? You can't tell in advance if you've allowed enough memory for someone else's mod." "5194": "Will our 64-bit allocation break on Raspberry Pi?" "5247": "Will the Transient storage be freed, or will you just take off its end until its gone?" "5265": "Is it better to keep track of how much memory is freed instead of total size?" "5286": "Why are you reluctant to have to constants be 64-bit integers?" "5367": "Did you pass different flags to VirtualAlloc for permanent and transient storage?" "5394": "What are the 'other reasons' for specifying a BaseAddress." "5461": "Is it possible the pool will be fragmented?" "5590": "Sign Off" --- name: "day015" title: "Platform-independent Debug File I/O" markers: "86": "Overview of the two classes of game file I/O" "330": "Today's goals (building a minimal set of I/O functions)" "408": "A brief lesson on the sad history of file I/O" "760": "The modern and better way of handling files" "894": "A first pass at the usage code" "1136": "Locking our janky code out of the release build" "1321": "Implementing the I/O functions in the platform layer" "1426": "File handles and CreateFile() breakdown" "1747": "GetFileSize() and GetFileSizeEx()" "2103": "A janky situation with ReadFile()" "2227": "An inline function, SafeTruncateUInt64()" "2595": "Step-through of our read function" "2821": "Making a write based on the read function" "3019": "Using the write function" "3209": "Step-through of the write function" "3400": "Editing the .emacs file" "3507": "Breaking the .emacs file" "3619": "An IMPORTANT note on the safety of file I/O code" "3735": "Q&A" "3774": "Will the game be able to carry on in spite of some big time failure, like a graphics device reset. And does software rendering make that easier to deal with?" "3868": "Would it make sense to call normal GetFileSize() and then assert that the high 32-bit value is zero?" "3960": "Would it be useful for us to write our own allocation function that specifically allocates sections of our already-reserved temporary memory? I am having trouble understanding why we are doing separate allocations." "4074": "Will we implement some kind of cloud storage for the writes?" "4135": "I know you removed it for now, but wouldn't a reserve memory method with an arbitrary size still introduce a failure point since it could fail like VirtualAlloc() and we have simply moved the burden onto ourselves?" "4199": "You can reload your emacs settings without blowing everything up each time with evalbuffer." "4255": "Are there any other benefits to doing one massive allocation, aside from having one failure point. Also does the order of properties in your structs matter when it comes to performance efficiency?" "4560": "Do games really usually write to a second file rather than using some soft of safe write function that won't overwrite it if it somehow fails?" "4651": "Do you miss multiple return values in C?" "4710": "Why don't we just map the file into memory?" "4759": "Will allocating a single amount of memory up front make it more difficult to selectively enable/disable certain features of the game, since there could be many combinations, each requiring different amounts of memory?" "4832": "Why does the order of fake_struct_a and b matter?" "4870": "Why did you do the byte macros, but hesitate on the swap? Is there some hidden complexity on pointer swaps?" "5075": "So structs with unions in them have bad performance issues?" "5111": "You mentioned IOCP (I/O Completion Ports) for async file I/O. Are you planning to use multiple worker threads? I've been doing some multithreaded epoll code on Linux, and it's a very janky API unless you're using one worker thread. There are even a few articles on LWN.net only about how to safely remove a file descriptor with epoll." "5187": "On the swap, why does it have to be a macro. Wouldn't a function do the job and cover the janky complexity with types in the macro?" "5226": "Why don't you define the swap macro to be #define swap(a,b){ type_of(a) temp...?" "5253": "Does ArrayCount macro work with strings?" "5266": "Won Chun: Async file I/O in Linux is nutty." "5293": "(Key Switches)Brown or blue?" "5333": "It (ArrayCount) actually works with string literals." --- name: "day016" title: "VisualStudio Compiler Switches" markers: "152": "Explanation of Warning and the Warning levels" "320": "Fixing warnings, and disabling warnings we don't want" "850": "Other command line switches that Casey normally uses" "1080": "Compiler intrinsics command line switch" "1140": "Disabling Run time type information" "1160": "Disabling exception handling" "1340": "Configuring for a 32bit build" "1860": "Windows XP VM Testing" "2372": "-MT vs -MD and why it matters" "2485": "-Fm Creating a map file and looking at it" "2770": "Why the names are mangled in the .map file produced with the compiler switch of -Fm" "3010": "Start moving keyboard input into the non-platform code" "3772": "Q&A" "3873": "Question: -Oi , Why would anyone not want it active" "3962": "Question: How do we add -Wx -W4 to the commandline switches if developing in VisualStudio" "4027": "Question: Would turning on -Od be a good idea to use in the normal build" "4083": "Question: Does compiler compilation always say finished in green" "4125": "Question: I think you mentioned something about not being a fan of rebindable keys, why no option" "4191": "Question: How much difference would be yielded if we disable the CRT" "4226": "Question: I could not see what you did to not have the key x messages not triggered" "4333": "Question: Would it be better to just pass which key was pressed to the non-platform code instead of in the platform code" "4412": "Question: If you build for say AVX2 but the user has a older processor, what happens" "4443": "Question: Will we move to a unified build system for all target platforms" "4482": "Question: Would not -Oi and -Od be clashing" "4521": "Question: Is there a way to make cl emit a human readable summary" "4532": "Question: Does the map file spit out data about struct memebers as well" "4563": "Question: Does not allowing key rebinding mess up on different keyboard layouts" "4637": "Question: Is the game currently linked to the dll version of the CRT" "4671": "Question: I know you won't be using any libraries, but how would you include unity clib and link to that" "4782": "Question: Is there any advantage to processing things in the main loop other then conceptual grouping" --- name: "day017" title: "Unified Keyboard and Gamepad Input" markers: "139": "Overview of the previous day's work" "311": "An introduction to functional programming" "644": "Methods for making our programs more functional" "701": "Rationale for moving keyboard handling out of Win32MainWindowCallback()" "877": "Finishing the keyboard processing code" "955": "Adding a fifth controller (the keyboard)" "1020": "Adding 32-bit and 64-bit compiler options to the build.bat" "1194": "Ensuring keyboard state persists across frames" "1355": "An Assert() that we didn't do anything stupid" "1430": "Finishing our directional stick code with deadzone processing, no zombies." "1776": "Using the deadzone values from MSDN" "2105": "Iterating across all the controllers in GameUpdateAndRender()" "2183": "Testing new input code" "2254": "Changing game_controller_input to work across both keyboard and gamepad" "2472": "Adapting the keyboard and gamepad code to the new structure" "2695": "Connecting the stick input into a fake directional pad" "2896": "Hooking up the real DPad" "3125": "Adding an IsConnected member to game_controller_input" "3187": "Buffer Overrun encourages some bounds checking" "3404": "Why did we overrun the buffer?" "3566": "Adding some last minute keyboard inputs" "3606": "Final Thoughts" "3748": "Q&A" "3770": "Check the array in the Buttons union, you might want 12 now that you've added start and back" "4134": "Is that some copypasta, or is it really supposed to be all MoveLefts?" "4284": "Could it be good to apply some integration on the keys, so we don't just set the value to binary -1/1?" "4376": "Can you talk about the deadzone being round vs rectangular at hardware USB, HID, and XInput API layers?" "4755": "Maybe it's a round deadzone?" "5020": "I'm 16 days behind, is there a better way to catch up than watching all the days on YouTube?" "5062": "For the build.bat, you can build for Windows XP 64-bit using 5.2 instead of 5.1" "5073": "On the inline method for GetController(), what happens if you pass in -1 for index?" "5150": "Can you do struct buttons_type (name the structure) and still get the benefits..?" "5199": "I don't get using Win32 prefix for function names when compiling for 64-bit." "5254": "I was thinking about processing game input in a separate thread so it is framerate independent, but I heard you could introduce input lag. Is that true?" "5326": "You said a circular deadzone would be good for gameplay, why don't you just make it circular? The deadzone would just be a little bit bigger." "5522": "DirectInput vs XInput, which is better?" "5597": "You deleted the Min/Max macro TODO..." "5643": "So when you use the ZeroController, why not just go *NewKeyboardController = {}?" "5729": "stddef should include offsetof(), you can use that to make your assert a little simpler." "5876": "Final Wrap-Up" --- name: "day018" title: "Enforcing a Video Frame Rate" markers: "100": "Discussion: Why we need to have an enforced video frame rate" "327": "Drawing and explaining the frame computation and displaying timeline" "635": "Explaining Variable Frame Rate Monitors" "1080": "Casey's Game Loop Design Overview" "1215": "The two audio choices we can use" "1523": "Multiple Monitor discussion" "1930": "Start implementing the enforced video frame rate" "2180": "Looping to ensure we are within the targetSecondsPerFrame" "2320": "Debugging: no input" "2441": "Compressing/Refactoring Clocking stats" "2945": "Implementing sleep to not melt our CPU" "3200": "Setting the Windows scheduler granularity with timeBeginPeriod()" "3630": "Q&A" "3668": "Question: If we are locking the frame rate. Would that not mean that someone with a lower end computer, would have a slower game speed to others" "3761": "Question: Even if you could get the refresh rate of the monitor, how do you sync with it on the vertical blink" "3832": "Question: Doesn't the sleep function go in the surrounding IF instead of the WHILE loop" "3947": "Question: Does Win32FillSoundBuffer need to come after the vsync loop" "4014": "Question: Check DWM.GetComposition if AERO is on" "4033": "Question: Could you explain the advantages or disadvantages to handling update and render on different threads" "4166": "Question: How would you adjust your memory management to work on devices with limited memory" "4182": "Question: Won't we miss frame rate due to the sleep" "4378": "Question: Can you fix the physics animation frame rate without fixing the missing frame issue" "4570": "Question: Why are we handling sound and video differently" "4587": "Question: Check if DDraw works on windows 8" "4612": "Question: Wouldn't you want to fill the screen buffer before you hit the flip point, so it can grab the screen at the flip point" "4683": "Question: Isn't DWORD an Interger" "4721": "Question: What do you think about having a fixed physics time unconnected to the drawn frame time" "4800": "Question: Any time you compute a world update should that not just set something that says if we get there early then wait." --- name: "day019" title: "Improving Audio Synchronization" markers: "133": "Intro" "211": "Audio Sync Conversation Begins (Summary)" "259": "#milkhit" "268": "Why audio sync is an issue" "330": "Ways to minimize the issue" "400": "Creating a Debug Diagram for audio sync debug code" "937": "Finishing up audio sync debug code" "1423": "Explaining and debugging debug code" "1800": "Bug in debug code encountered" "1891": "Addressing bug" "2100": "Compiling and running successfully" "2130": "Observing weird gaps in sound" "2155": "Not tracking frame time correctly " "2310": "Addressing the weird gaps" "3000": "Running new code for debug diagram. Sound card read seems unreliable" "3180": "Sound stream has to be continuous. Figuring out how far ahead of the current play cursor we should be writing" "3528": "Discussing possible solutions to improve audio sync" "3755": "Improving audio sync" "4040": "Making a running log" "4120": "Getting a log of our audio to do some important things" "4320": "How much granularity we have" "4580": "Audio latency issue found" "4790": "Closing remarks" "4828": "Q&A" "4873": "Are you setup to use ASI Sound Drivers?" "4925": "Is your audio pointer code calculating independently of the variable-fixed visual frames per second?" "5075": "What sort of problems can high audio latency introduce?" "5238": "Could you use that anonymous union struct trick to access the members of bitmap info header structure more easily?" "5327": "Question about switching Audio APIs" "5502": "Why are we ignoring write cursor?" "5590": "Would splitting related functionality in separate files help?" "5650": "If we use the play cursor as offset, could we not overwrite previously written audio data?" "5977": "Comments about Audio APIs again" "6014": "Would rendering at 60 FPS help with the audio latency?" "6076": "Could you change latency values?" "6093": "Is it possible that OBS is affecting the audio latency?" "6122": "Closing remarks" --- name: "day020" title: "Debugging the Audio Sync" markers: "164": "Fixing an off by one error" "312": "Explanation of off by one errors" "433": "Overview of the state of our audio code" "665": "A breakdown of how time is spent during each frame" "847": "A possible, though not great, solution to audio latency" "982": "Tradeoff between audio lag and input lag" "1071": "Falling back to a little bit stupider" "1318": "Beginning to change the code for the audio output method" "1368": "Finding the minimum expected audio latency" "1651": "Converting to seconds using dimensional analysis" "1894": "Writing sound based on the audio latency" "2054": "Great aside about keeping code fluid and a bit messy in the early stages" "2220": "Determining the position to write the audio to" "2787": "How to deal with the low latency case" "3076": "A puzzling situation" "3180": "The aha moment" "3334": "The approach we will be taking for low latency" "3456": "The higher latency approach" "3674": "Another snag" "4028": "Putting our approach down in words" "4382": "Implementing the two case latency handling" "4714": "Do over due to deleted code" "4808": "Putting in the latency branching code" "5015": "Determining if the sound card is latent" "5162": "Mapping the WriteCursor and the PlayCursor into the same space" "5271": "Overview of the code determining how to write the sound" "5400": "Cleaning up" "5482": "How can we possibly predict how many bytes the game should write?" "5582": "Getting sound output separately with GameGetSoundSamples()" "5805": "More cleaning up" "5863": "Computing SafetyBytes" "5946": "Implementing GameGetSoundSamples() in the game code" "6010": "Testing is surprisingly successful, no bugs? NO WAY!" "6167": "Improving our sound output debug drawing" "6505": "Recording some additional details in our markers" "6996": "An assertion fires and some cleanup" "7113": "First look at the debug drawing output and adding global pause key" "7358": "Taking a good look at the debug drawing output" "7480": "A couple early questions" "7547": "Final Thoughts?" "7602": "Drawing another debug marker" "7853": "Improving our estimate of the PlayCursor position to reduce latency" "8279": "Taking a look at how our estimate lines up" "8353": "Drawing our 480 sample jitter window" "8535": "Q&A" "8578": "Did you try the audio without OBS?" "8655": "Is it inexpensive to query for the play cursor and the write cursor?" "8703": "Audio seems to be the most complex part until now, which will be the next most complicated thing?" "8818": "Audio asserts are a pain when you're debugging other things. Change to log messages." "8866": "If we had a buffer that played from start to finish, would it be a valid syncing method to manually set AudioTimer = VideoTimer?" "8925": "Fully visualize waveforms and remove gradient. Turn entire thing into massive audio visualizer." "8982": "Could you please increase ToneHz to 512, my crappy laptop speakers can't output 256?" "9029": "Will this audio system be able to handle music and sound, or will the game have to mux the audio for us?" "9068": "How will you make sure that you don't have regressions in some parts that are not that easy to spot right away?" "9114": "I'm sorry if I'm being slow, but I still don't truly understand why exactly the audio is jumping. It just seems like we should be able to handle it more simply." "9159": "Why is the pitch of the sound changing after the game has been running a little while?" "9595": "Callback to earlier half of question: (I'm sorry if I'm being slow, but I don't truly understand why the audio is skipping.) The original audio skipped when we moved the latency to be inside of three frames." "9745": "If it's not too much of an issue, can we have line numbers on the side when you are coding so we can get a grip of where you are." "9788": "It's more likely to be the accumulation of a small value onto a larger value that is a numerical problem. Mantissas not lining up." "9843": "Wrap-up" --- name: "day021" title: "Loading Game Code Dynamically" markers: "89": "Intro to the episode" "186": "About implementing and using a scripting languages" "375": "Benefits of loading game code dynamically" "509": "Starting on dynamic code loading" "698": "Separating platform and game code to different translation units" "956": "Getting functions from game dll to the platform executable" "1469": "Getting Functions from platform executable to the game dll" "1860": "Searching compiler flags for building a dll" "2118": "Dll main" "2408": "Exporting functions from a dll" "2847": "Loading and unloading the game dll on the fly" "3017": "Moving local persist variables from the dll to game_state" "3151": "Avoid locking the dll to allow rewriting" "3720": "Episode recap" "3817": "Q&A" "3831": "-LD to build a dll and removing incremental building" "3983": "Question: We have small code right now. How does dynamic linking and compiling to an exe work with huge games that are multiple gigs?" "4059": "Casey spoils tomorrows stream by telling people not to spoil it" "4080": "Short recap on loops" "4228": "Question: Do you recommend playing around with dll files, or are they mainly used in specific cases?" "4265": "Question: Can someone now create a dummy handmade.dll and use it to intercept the GameUpdateAndRender function to get a pointer to game memory and change stuff. Is security something you will cover in a later stream?" "4414": "Question: We've got a tiny application right now so if code takes minutes to compile, how are we going to do what we just did?" "4568": "Question: Would you be able to load the dll yourself using ReadFile() and implement getProcAddress() as well, assuming there's an easy way to make the memory executable like mmap()" "4696": "Question: Is this technique still possible without using passing of the large memory blob between the dll and the exe?" "4860": "Question: Does the dll prevent the compiler from inlining?" "4907": "Question: How are we going to implement dll's on Linux/Mac?" "4982": "Question: Are you ever going to write the platform layers for other platforms on the stream in the far future?" "5042": "Question: Is the process roughly the same for doing the Linux equivalent of sharing libraries?" "5142": "Question: Your #define typedef magic kinda bugs me, in that it hides the arguments/return type away from the implementation. How much of a win is having the signature in one place?" "5214": "Question: How does Windows manage memory in a dll? Is there a dll process page? Where are variables made/the statics stored? How is heap managed when allocated from a dll?" "5834": "Question: Doesn't Windows know [who called it] by the instruction pointers leading up to the VirtualAlloc() call?" --- name: "day022" title: "Instantaneous Live Code Editing" markers: "150": "Recap, and cleaning up DLL creation code" "445": "Trying to set the name of the .pdb file" "575": "PDBPATH and setting the name of the .pdb file for handmade.cpp" "910": "Found the command, now Setting random file name with %date% and some crazy batch syntax" "1140": "making DEL less intrusive, by piping output to a file" "1440": "making the reload of the .dll faster" "2100": "Compare File Times" "2389": "Finding the the dir of the executable so we can find the .dll" "3025": "String Processing Code" "3685": "Q&A" "3744": "Question: How do you manage to time your coding so perfectly" "3754": "Question: You mentioned yesterday you had something from a previous days but never did" "3811": "Question: Will this capability be in the shipping game or will it only be for debuging" "3855": "Question: Does the reload of the dll reset the game" "3907": "Question: How much time have you spent planning this game prior to even starting on day 001" "4003": "Question: Are you building the game in two sections, Games layer and a Platform layer" "4041": "Question: Since DLL's are not on linux or OSX how will we handle automatic reloading of the code" "4093": "Question: Why don't you use dynamic buffer allocation" "4149": "Question: You said that you are going to show us how to make a game well, what qualifications do you have for that" "4276": "Question: Could you expain your method of compressed programing in writing" "4362": "Question: When findFirstFile is called does windows actually read anything from disk" "4386": "Question: One way to abuse the fact that the game is in a seperate dll is to open the game part up to modders and modders tools" "4443": "Question: One common theme in the series so far is that you should not clearn up OS memory on shutdown but OS objects will possibly need to be cleaned up on DLL reload? correct?" "4629": "Question: Are we going to see the process of designing the game" "4831": "Question: Can you give some examples of code that won't play nice with the dynamic code reloading" "4959": "Question: Do you have any opinion on lua for a scripting language, config loading" "5049": "Question: Do you think this method of hot reloading of the code can be used in other types of software other then a game" "5101": "Question: Do you think there is a case for DSLs instead of using C" "5180": "Question: One benefit of lua is that you don't have to recompile" "5205": "Question: Is the game engine going to be generic or custom to this game" "5296": "Question: Do I recommend C over C++" --- name: "day023" title: "Looped Live Code Editing" markers: "165": "Review of the live code editing feature" "253": "Building a demo to show gameplay tuning workflow" "540": "Testing the demo" "680": "Adding jumping" "850": "Necessary improvements to square drawing" "944": "Jump tuning" "1012": "Problems with gameplay tuning and a solution" "1099": "Making a loop editor for code" "1173": "The ease of storing the input stream in memory" "1225": "Writing it out to disk instead" "1309": "Creating a win32_state structure that we can pass around" "1350": "Press L to record" "1481": "Usage code for recording and playback" "1536": "Implementing the record and playback functions" "1694": "Functions to handle the recording output file" "1864": "Functions to handle reading in the recording file" "1942": "Some code to loop the input playback" "2096": "Testing the recording and playback" "2268": "Bug-fixing" "2406": "Input record success, moving on to record game state" "2547": "Implementing recording of game state" "2874": "Testing, and a failure to loop" "2983": "Successful looped editing demonstration" "3290": "Playing around with window types" "3587": "Transparent Window! And Access Violation!" "3716": "Improvements to transparent window." "3827": "Final Thoughts" "3984": "Q&A" "4010": "Does Win32PlayBackInput need to return status in case the file read fails and/or reaches the end, since in those cases the function output data structures will be stale or invalid?" "4116": "Will this break when you make changes to the game_state structure?" "4290": "Why didn't you use a switch for all the VKCode stuff?" "4314": "Since it's mostly zeroes, do you think it'd be worth writing out the game state in a sparse way using a simple RLE or something, or is performance sufficient? Or perhaps that would make performance worse?" "4402": "What's on the schedule for next week?" "4437": "Are you going to show how to create more debug tools like this?" "4501": "Regarding saving game state for recording, won't we run into problems if we port a system that doesn't allow us to specify a base address?" "4568": "Any chance for a high-level overview while cleaning up?" "4605": "Isn't a two gig snapshot of your game memory crazy huge though?" "4757": "I think your sine wave is a tad bit off on land of the jump." "4778": "I'm thinking maybe less about the error and more about what happens at the end of the stream when it loops, doesn't that generate an extra repeated input event played back, or am I missing something?" "4885": "Can you clarify if function pointers are part of that game_state block, maybe elaborate on what could ever cause it to fail or misalign?" "5066": "How can we make the playback work if we have no base address?" "5140": "Wouldn't the address spaces of two game_state's clash?" "5220": "Would a memory-mapped file that doesn't commit to disk be faster to read/write from?" "5278": "I thought you were going to use the memory snapshot as a game save, but you're using it like a save state in an emulator." "5310": "How easy do you think it is to re-arrange an existing codebase so that it supports the instant live code editing feature, and what steps would need to be taken to get there?" "5402": "Will there be a Christmas special?" "5418": "How will replay work once you have start-up logic for the game? How will it be skipped? Will it just work?" "5464": "Clarification of earlier question (How often do you look up code?) How often do you study code on your own?" "5602": "Perhaps ReBaseImage() regarding loading dll at location?" "5631": "Suggestion to add -mix to the linker for fixed dll location." "5714": "How long did it take for you to get to a point where you can concieve of a feature and with little effort know exactly what you need to accomplish to realize that feature?" "5923": "Couldn't you create an offset pointer struct which overloads the unary * operator?" "6043": "Have you got some good explanation on how you architect code, is that in the text you wrote about your work on the Witness?" "6126": "I have to spend a lot of time unlearning what I was taught just to get to features which should be easy, but were made hard by the kind of programming I learned in school. Have you had a similar painful unlearning process?" "6291": "Wrap-up" --- name: "day024" title: "Win32 Platform Layer Cleanup" markers: "65": "Goals for the day" "170": "Fixing a dumb audio bug" "498": "Failing to find a supposed SUCCEEDED related bug" "588": "Concerns about WasDown/IsDown" "745": "Fixing a bug in our gamepad input handling" "877": "Fun? with Krita" "1007": "Back to Paint to illustrate the input bugfix" "1257": "Changing our renderbuffer to have fixed dimensions" "1419": "Improving the build.bat file" "1500": "Changing the write location for our .hmi files" "1657": "Writing some helper functions to create the dll path" "2031": "Step-through" "2172": "Taking our helper functions and using them elsewhere" "2423": "Testing the changes to input recording" "2482": "Input Assert firing and turning off Topmost window" "2565": "Changing Win32GetLastWriteTime() to use GetFileAttributesEx()" "2762": "Using DeviceIoControl to potentially speed up input recording hitch" "3066": "Removing stub functions from handmade.h for easier porting" "3230": "Looking at improvments to our 1GB VirtualAlloc()" "3312": "Whiteboard illustration of virtual memory" "3540": "Looking at real world virtual memory addresses" "3699": "Translation of virtual memory addresses into physical memory by the TLB" "3846": "So what are large pages?" "3926": "Changing VirtualAlloc() to use large pages" "4038": "Putting aside the large page support for later" "4106": "Q&A" "4190": "Can we go over really fast an overview of the game recording code?" "4456": "When you're saving the game_state snapshot, how big is the file?" "4525": "Can you check if the StringLength() needs a win32 prefix, or is this game code?" "4537": "How many lines of code is the finished game estimated to be?" "4562": "Maybe use two randoms in your batch file to get a more unique file name?" "4580": "Any advice on where I could go or what to do to pick up a bit more coding or knowledge experience?" "4625": "What is a good example of well-written game code? Everyone talks about the DOOM source code." "4649": "Assuming you want to record exactly what happens in the game, how would the looping handle random values; Say enemy bullets that are fired at random angles?" "4703": "If we dump memory to disk in a large-scale application, wouldn't that cause more than a 1GB footprint for every state?" "4774": "I don't get the stuff where you declare a variable without initializing it, and then you use the address to it in a function call. Is that a dummy thing, or what is it used for?" "4909": "You can make the recording instantaneous using copy-on-write pages." "4978": "Would the sparse file flags dropped the .hmi file size?" "5009": "I'm still not sure why we're using the Windows API to get memory instead of the standard library. Why are we making Windows calls if we are supposed to be doing everything from scratch?" "5089": "As the game grows, how are you going to partition the game memory between systems to keep the record-and-playback feature working?" "5120": "Would it make sense to temporary lessen the size of game memory we don't use at the moment anyway?" "5154": "Are you happy with the timing FPS results? I found an old article on _rdtsc() for more accurate timing." "5221": "When would the Mac code start? I am following with Windows in a VM and it's really slow." "5266": "Is there any negative effects of making the page size bigger?" "5387": "How do you calculate the size of a struct?" "5498": "Can you add line numbers, so those of us following along have an easier time?" "5630": "I believe some people think that the game_state is saved every time with the input, whereas it is only saved at the beginning of the recording and then modified through input playback." "5661": "Do you think the recording technique will run into problems if we have multiple threads using the game_state?" "5707": "If VirtualAlloc() does not guarantee contiguous memory, could this pose a hindrance to cache optimizations?" "5805": "Where can I get earlier versions of the code? The link only gives me the latest version." "5835": "Wrap-up" --- name: "day025" title: "Finishing the Win32 Prototyping Layer" markers: "107": "Plans for today" "260": "Getting the actual monitor refresh rate with GetDeviceCaps()" "627": "Testing monitor refresh rate getting" "677": "Preparing for future multi-threading" "1022": "Adding mouse debug functionality to our game input" "1418": "Getting the state of the mouse buttons" "1707": "Testing mouse button functionality" "1927": "Making improvements to replay code" "2000": "It's time to get piggy!" "2125": "Allocating memory for our replay buffers" "2281": "Changing Win32BeginRecordingInput to write to memory" "2539": "Swapping out WriteFile() for CopyMemory()" "2762": "Testing our new recording technique to much disappointment" "2940": "Poor man's profiling" "3148": "Stepping through to find the real culprit" "3226": "Removing SetFilePointerEx() for a massive speedup" "3331": "What we were going to do with memory mapped files" "3446": "Let's try it anyway" "3793": "Pulling out input file processing into WinMain()" "4045": "Step-through and removal of an assertion" "4135": "Debugging the memory mapped file failure" "4344": "A peculiar fix" "4398": "Review of the recording code" "4472": "Splitting the file output into two streams for more speedup" "4700": "Testing with some notion of success" "4874": "What's the memory bandwidth of Casey's machine?" "5116": "Looking at multiple sequential records" "5296": "Removing/disabling some debug code for now" "5429": "Final Thoughts" "5507": "Q&A" "5567": "Maybe first copy is causing alloc and zero on fault, maybe a second copy would be fast" "5728": "An interesting part of this project is that you're implementing all the compenents yourself that you'd take as given in an existing game engine. That said, do you intend for these components to be reusable in future projects?" "5792": "Why the pig hat?" "5804": "Why don't you use the Visual Studio profiler and anaylze performance?" "5826": "Remark about 300ms being 10 frames, not 3 frames" "5859": "Does it lag if you save to a smaller file size?" "5939": "Isn't the CPU Memory bandwidth only valid for on-die memory?" "6023": "Is the intent of saving the complete game state to support something like a rewind function that Braid allows?" "6067": "Will you do a string pool?" "6086": "When you say the platform non-specific layer, does that mean game code and renderer and logging sorts of things, or is there a sharper distinction between some of those?" "6135": "A quick test on my PC gave me around 3 GB/s..." "6197": "Is it time to split the source into more files?" "6220": "Would a non-caching write be faster for the memory copy? You know the SSE write instructions that bypass the cache?" "6314": "When are the four .hmi files created?" "6350": "...An AMD A8-6400k (Follow-up to 3GB/s memory bandwidth mention)" "6457": "Are you going to do a moblie port? (Android for example) Would the game loop of a mobile game be any different?" "6531": "How about disk write speed and access time?" "6570": "Why is the CPU even involved in a memory copy like this?" "6661": "What was the reason for choosing GetCursorPos() instead of just responding to the WM_MOUSEMOVE message? Is the message pump not fast enough?" "6685": "Have you ever programmed in Java? For how long?" "6747": "(continuation of Why is the CPU even involved question) Wouldn't the copy speed mostly depend on how quickly memory from one part of the memory gets to the CPU and back? In fact, in my mind it seems like large copies are something that could skip the CPU entirely unless it has something to do with paging." "6872": "Is it worth writing games in Java?" "7023": "Are you in dual-channel write mode on your system?" "7033": "Does the Megabytes have any effect on the performance of the memory?" "7058": "Tom Forsyth comment about modern DMA units not being available to users" "7119": "What do you think of Test Driven Development?" "7167": "Can you explain the bit shifting?" "7464": "You can create a performance heavy application in Java without the garbage collection if you configure it to run as real time instead of virtually" "7593": "Do you consider Visual Basic a programming language?" "7636": "On the memory CPU speed, I see the answer is that the hardware doesn't do this. I guess I'm just envisioning a system where the gigabyte of memory never visits the CPU. I am envisioning a system where the memory can receive an instruction that says locally move a gigabyte over to this location" "7731": "Tom Forsyth comment on using LARGE_INTEGER instead of the bit shifting" "7860": "In your mind, what would be a good way to demonstrate to a potential employer proficiency in the type of engine programming you are teaching?" "7958": "Thanks (And a comment from Casey on the success of the stream)" "8009": "What defines the boundary between a high-level language and a low-level language?" "8200": "When will you start actual game logic?" "8213": "Have you heard of the Rust language?" "8251": "Have you ever dealt with programmer burnout? Or how do you deal with the fact there are days almost no code gets written and on some days massive amounts of code gets written?" "8428": "Any source or book recommendation for understanding the concepts you used better?" "8469": "Have you seen Game Programming Patterns by Robert Nystrom? Are you going to use any design patterns?" "8551": "Do you find it useful to learn many different languages to gain perspective?" "8711": "What do you think about using VCS for one man projects?" "8753": "What's your mindset when looking at a problem that's new? How you approach a new coding problem that you have no pre-defined idea how to solve?" "8793": "Will you write a book after Handmade Hero is done?" "8806": "How long have you been in the industry?" "8819": "I've always been a hobbyist, the more I've learned over the last year, the more I love programming. In your opinion is going back for a four-year CS degree a waste if I want to make things that don't suck?" "8842": "Perhaps the problem with high-level languages is that they are less general, but more domain specific in the first place" "8885": "How does your source code control differ from something like Git or SVN?" --- name: "day026" title: "Introduction to Game Architecture" markers: "0": "First day of Programming the Actual Game" "176": "We'll know how everything happens above the platform layer" "365": "Software Architecture" "410": "...vs. Real Architecture" "580": "Taking the metaphor literally: UML as Blueprint" "660": "The problem with that" "797": "An alternative view: Software Designer as Urban Planner" "915": "The freedom of software: malleable architecture" "1045": "Software Design: How the city works" "1235": "The Art of Defining Boundaries" "1296": "Why you want boundaries" "1541": "Metrics for Architecture" "2052": "Game Architecture" "2095": "What we've done" "2287": "What's to come" "2345": "Principles" "2548": "Input->Update->Render" "2694": "Coupling and the Cache" "2934": "Resources: Load vs Stream" "3358": "Immediate mode vs. Retained mode" "3780": "Is Immediate Mode/Retained Mode like IoC (inversion of control) / Dependency Injection [n.b. No it's not -ed]" "3794": "Is it okay that we're using a fixed time step when users might not make 30fps?" "3860": "Game won't run at a fixed timestep: we'll take in t as a param" "3905": "Are you going to work with Virtual File Systems to store resources?" "3934": "On rendering while updating: What about when the render of something at the top of update() would've changed if we'd known about something that's at the bottom?" "3985": "Update dependencies are a general problem that should be solved by the architect" "4045": "What happens when you need to render in a different order than you update?" "4094": "Explain the variable, demands Naysayer88" "4156": "How do you handle update/render at different frame rates?" "4200": "When you say do update/render together, do you mean do it per entity?" "4235": "Are we planning on networking?" "4260": "How are you going to handle shaders?" "4271": "What language are you using primarily? Where can we view old streams?" "4330": "Would a memory mapped virtual filesystem be a bad move?" "4419": "Will handmade use loading or streaming?" "4432": "Can you go over how streaming fits in to the GUAR?" "4509": "Will combining update and render limit multithreading?" "4607": "Treatise on threading" "4843": "Since the eye can only see at 70fps [citation needed -ed], should we set a max fps?" "4888": "How will we handle vsync?" "4928": "Couldn't you store groups together to win some on a split update / render?" "5005": "Async job system?" "5060": "Whennn willl youuu worrrkkk onnn theee gammmeeee?!?!?!?!?!11!!" "5093": "Will we make a physics engine?" "5117": "Is it okay to post a js/html5 port on my github?" "5214": "Thanks / Next time on... / Holiday Hours" --- name: "day027" title: "Exploration-based Architecture" markers: "0": "Welcome" "142": "Evolution of a Project" "403": "How to drive towards an unknown destination" "576": "The dangers of pre-planning" "747": "The exploration two-step" "982": "Game engine goals" "1021": "LoZ Influence" "1196": "Tile Map - What to modernize, what to keep" "1452": "Goals for Procedural Generation of Levels" "1872": "Rich Combinatoric Interactions" "2084": "There's no plan, folks" "2166": "The coding begins" "2190": "Add something we forgot" "2288": "Clean out old debug visuals/sounds" "2555": "Resolution goals" "2850": "Let's draw a rectangle" "2970": "What to know about bounds for drawing geometry" "3261": "Coding drawRectangle" "3768": "Rounding floats to ints" "3932": "Testing drawRectangle" "4248": "What's that link error when you compile?" "4312": "What things are good to put in a portfolio?" "4335": "Does this work?" "4346": "Thought on making this all completely functional?" "4450": "How do you do compression programming with big teams?" "4560": "Do you think writing structs for things like vectors is good?" "4655": "Are you going to use linear texture layout or something fancy?" "4670": "If C didn't exist what language would you use?" "4730": "Where can we find out info on engine architectures?" "4786": "Particulars on procedural generation? Will dungeons regenerate every time you enter" "4849": "Will the game be generated as you go?" "4918": "What with Jon Blow and Variables?" "4987": "Will you use fixed point?" "5027": "How old were you in the picture on mollyrocket.com?" "5059": "Why are subpixels better than pixels?" "5126": "Will you be growing a beard?" "5138": "Are you going to use linear texture layout or something fancy and swizzly (repeat, but answered this time)?" "5183": "Would the player really notice a 1-2 frame lag of sound in this game?" "5248": "How different would initial rendering be if the game was vector-based?" "5295": "You cut me deep, Casey." "5312": "What's bad about OOP?" "5450": "I'm having trouble understanding the sound stuff, should I worry?" "5513": "Did you work on NWN2?" "5571": "Can the compiler optimize the rect draw based on (lack of) aliasing?" "5670": "Will we be doing Antialiasing?" "5676": "Future old-man baldness strategies?" "5694": "Can you explain the subpixel stuff via video?" "5710": "Are you making a runescape clone?" "5715": "What do you suggest for mobile game dev?" "5730": "Will we be using DX11 for the rendering layer?" "5745": "Pokemans? [no]" "5756": "Disparaging Python?" "5799": "Dinosaurs? [are cool]" "5803": "How can I get a (good) job (like you)?" "5814": "Lazer sharks? [also cool]" "5818": "Mounts? [probably not?]" "5821": "How often do tech limitations matter?" "5882": "Member functions?" "5896": "Owl of shame is navi?" "5911": "How will you use the game memory block?" "5941": "What if MinX and MaxX are both less than 0?" "6005": "In a perfect world... Pokemans? [no]" "6029": "Moral message? Hired a writer?" "6047": "Handy Links / Holiday Hours / Happy Coding" --- name: "day028" title: "Drawing a Tile Map" markers: "54": "Overview of the day" "210": "Floating point color discussion" "1010": "Actually doing the color in floating point" "1420": "Showing some of the possible structs we will want to pull out" "1503": "Starting a basic tile map" "1690": "Looping through the tilemap to draw" "2252": "Getting a player to the screen" "2786": "Basic character movement" "2880": "Debugging slow player movement" "3514": "Q&A" "3540": "Question: Is Sleep() still making us miscalculate the fps" "3675": "Question: dtForFrame is only in one of the inputs" "3787": "Question: Maybe we should sync our frames with vsync due to it dropping our frames" "3830": "Question: On the topic of tilemap size maybe use smaller tiles then use 2 tiles for doors" "3866": "Question: Why not use anything created before like sdl, opengl, and so on (new person question)" "3943": "Question: Fixed-point or floating point" "3982": "Question: Would not anyone expect 4pixels per frame at 60fps be a little jerky" "4048": "Question: Yesterday you discussed explorative programming. How do you compare that with AGILE development style?" "4205": "Question: Was procrastination a problem for you?" "4293": "Question: Could all the print output cause the lag in the input?" "4327": "Question: Use space on top/bottom for UI" "4354": "Question: Can we pack the colors in a struct?" "4361": "Question: Is there a reason to set the tiles to a square other than ease of use?" "4400": "Question: Do you add anything to your almond milk other than soaked almonds and water?" "4404": "Question: From yesterday's stream how can you tell the difference in how to change the direction of your design or is that a fundamentally hard problem" "4577": "Question: Would it be bad to do a rectangle tile, since you get a rectangle by doing an ortho view of it anyway?" "4687": "Question: What debugger do you use on Linux?" "4775": "Question: Why do we see 9 threads on the program exit?" "4983": "Question: Are we locked into a tile size once we get going or can we make that dynamic per level or room in the future?" "5077": "Question: What about selling t-shirts?" "5098": "Question: With your compression based programming do you find yourself writing facades for everything so you and others can interact with the modules" "5175": "Question: Why not use Clang?" --- name: "day029" title: "Basic Tile Map Collision Checking" markers: "150": "Review of what's currently been done" "197": "Clearing the screen to black and offsetting the drawable area" "409": "Player collision with the tilemap" "1043": "Moving player initial position inside the map" "1231": "Clearing only the parts of the screen not drawn on" "1390": "Function for checking if a point is occupied and tile_map struct" "1625": "Accessing tilemap data as 1-dimensional array" "2116": "Adding player width to the collision" "2270": "Making player change the map when walking through a door" "2636": "About storing all tilemaps in one big structure" "3028": "Start on storing and accessing multiple tilemaps and the world struct" "3660": "Short recap on where we are" "3736": "Q&A" "3790": "John Blow points out we haven't initialised the world struct members" "3823": "Question: Why does player sometimes stop a pixel before the wall?" "4476": "Question: Are your variables for tilemaps too similar to each other or am I just easily confused?" "4572": "Question: Is there an advantage on using bool32 instead of using bool 8-bit?" "4627": "Question: Can you go over briefly how to encode the tile data in a single uint32?" "4675": "Question: Why does left and right side collision work but not the top and bottom?" "4843": "Question: Why save TileWidth and Height if those values never change?" "4862": "Question: What are the differences between structs and classes?" "4994": "Question: Do you always put int32 or can you use only int?" "5085": "Question: So int32 is because you want to make the game for 32bit computers?" "5165": "The player moves faster diagonally than it's supposed to. Are you planning on fixing that?" "5230": "Question: I'm not familiar with #define, what is it used for?" "5314": "Question: When you use int32 does it have a different influence on the code than normal ints?" "5405": "Making the platform header C compliant" --- name: "day030" title: "Moving Between Tile Maps" markers: "190": "Recap" "396": "About the process of writing code; Messy first, clean after" "478": "Passing information about tilemap" "647": "Checking if player is moving to a different tilemap" "771": "Finding the next tilemap and querying the point" "2167": "Calculating the position in the new tilemap" "2575": "Storing X and Y positions relative to the tile" "3367": "Moving the player on to the new tilemap" "3649": "Floor instead of truncate" "4248": "Q&A" "4312": "Question: Can you talk about the inline keyword? Do you apply any strategies to make sure the compiler does not ignore the request?" "4393": "Question: Are we using C or C++?" "4487": "Question: How did we start the code for the game?" "4507": "Question: What's so bad about including math.h?" "4554": "Question: Why not substract 1 if input is under 0, instead of using floor()?" "4629": "Question: I thought integers were faster to compute than floats, even if the cpu has a floating-point unit." "4783": "Question: How do you decide when to pack things in a struct?" "5248": "Question: Why would we care about screen coordinates? Isn't that just platform code." "5366": "Question: Are you going to make walls obstruct the player the same way the player currently obstructs the walls?" "5417": "Question: Can you explain the raw_position and canonical_position again?" "5536": "Question: Instead of checking three points on the player, wouldn't it be better to check only the side the player is moving towards?" "5679": "Question: Why not have a single set of coordinates for the player that maps the player to a world position?" "6134": "Question: Are there any consequences of using inline in early development, i.e harder debugging?" "6202": "Question: Wouldn't it be better to call the X and Y variables something more descriptive?" "6352": "Question: The game will happen in whole screens without any scrolling or camera movement?" "6493": "Question: Could you explain how pointers/references are working or what you use them for and why?" "6542": "Question: Was there ever a point in your career where you used these unfortunate structure packing practices?" --- name: "day031" title: "Tilemap Coordinate Systems" markers: "0": "Welcome / Recap" "226": "On Scrolling" "294": "Scrolling for Free" "404": "Preview of Coming Attractions: Math Functions" "673": "Looking at floorf" "787": "SSE2" "1188": "Optimization flags: letting the compiler do it for you" "1459": "Math utility layer" "1647": "Trig/Vector Math Looms" "1728": "Coordinate Systems: Why we want them" "1981": "Screen coordinates vs All Math Ever" "2404": "Defining size in pixels and meters" "2880": "TODO: Packing our tilemap indexes" "3454": "TODO: Resolution-independent tile-relative position" "3568": "Q&A" "3604": "Will we be making a map editor?" "3625": "What were you talking about in terms of fast floor?" "3669": "Do enough people have SSE4? (n.b. steam hardware survey: 77% have SSE4, 99.8% SSE3)" "3837": "Can you not store anything and just regenerate everything from seed?" "4011": "Suggestions for speeding up floor (/fp:fast)" "4269": "Why do you do 'Result = foo(); return Result;'?" "4465": "Is it a good idea to be drilling down into intrinsics this early on?" "4547": "Is tile-relative for the real32 coordinates better than tilepage-relative?" "4710": "Why not just store location in world coordinates and div/mod to get tile info?" "4796": "Could our sparseness let us better use the top 28 bits of the tilepage index?" "5042": "Do you know of the intel intrinsics guide?" "5126": "Why is all our game-specific work so far in handmade.cpp?" "5205": "Are we going to move the origin to the bottom left?" "5234": "Line-drawing suggestion" "5283": "Will you be able to find ARM equivalents to your intel-specific instructions?" "5376": "How are we going to deal with different types of tiles?" "5435": "Week Roadmap / Outro" --- name: "day032" title: "Unified Position Representation" markers: "97": "Recap on what we're set out to do" "375": "About canonical position and using it for the player position" "787": "GetCanonicalPosition() to RecanonicalPosition()" "1922": "Debugging the new code" "2294": "Movement units from pixels to meters per second" "2469": "Recanonicalize edge case debugging after assertion fail" "3004": "Back to changing movement units" "3220": "Casey enjoying the little things" "3461": "Debugging player position" "3822": "Q&A" "3859": "Would this be the time to put on screen text for debug info?" "3915": "What is the variable called 'Gray'?" "3955": "How does the difficulty of conceptualising this type of code compare to say coding the backend to a web application?" "4023": "The window title bar is a nice place to spit out some text!" "4057": "About replay buffers: I don't think we ever use the 0th buffer in the Win32State" "4381": "When do you decide to add visual cues to help with debugging?" "4468": "What are your thoughts on the progress you make daily?" "4565": "Does the code actually handle skipping a tilemap?" "4617": "Can the player go diagonally through two wall tiles joined by corners with the current collision detection code?" "4699": "Why are you so fond of inline?" "4838": "Are you going to have input envelopes for feel like acceleration and fricksion?" "4864": "Can you explain what you meant by canonicalization in some simpler terms?" "5171": "Would this kind of code be good for unit tests/fuzz tests to make sure strange corner cases don't creep around?" "5230": "Are there reasons why programmers of older adventure games chose to move the character around the map and not vice versa?" "5372": "Earlier you said const is ugly? Ugly because of how it looks or for some other reason?" "5509": "What's your preferred 2D coordinate system? Y going up or down?" "5568": "Now that there's no raw_position can we rename canonical_position to position and recanonicalize to fix or rebase?" "5598": "Will we be using the tilemap for path finding or some other way to get smoother movement?" "5631": "Will you release your version control system?" --- name: "day033" title: "Virtualized Tile Maps" markers: "123": "Review of position representation" "155": "Today's agenda" "235": "world_position and changing y-axis" "720": "the problem with floating point for positions" "998": "solution: integers and floats" "1173": "sidebar: scrolling the screen works fine too" "1207": "big idea: tile chunks and sparse storage" "1593": "implementing our new coordinate system" "1856": "tangent: toroidal topology" "2155": "back to implementation of new coordinates" "2238": "extracting chunk coordinates from a world_position" "2645": "implementing tile chunks" "3021": "Setting up test data" "3050": "emacs keyboard macro roulette" "3246": "rendering from chunks using new coordinate system" "3287": "super piggy!" "3525": "debugging commences" "3648": "success" "3680": "greed: simple scrolling" "4059": "success again... finally" "4104": "Q&A" "4146": "Why not compute the chunk mask from the chunk shift?" "4444": "How did you generate the map? (A: he hasn't yet, it was typed in)" "4466": "How will you do a third dimension in the new coordinate system?" "4564": "How will you handle screen boundaries with the new chunk size?" "4626": "Is a chunk a quarter of our test map?" "4658": "How about operator overloading?" "4698": "Shouldn't we be thinking about networking and threading from the start?" "4775": "What does 0xFFFFFFFF represent?" "4842": "I'm surprised by your choice to flip the y-axis. Does it really make the math that much easier?" "4977": "I've never used hex literals, I use UINT32_MAX" "5037": "Why not program at a higher level?" "5169": "Why introduce meters?" "5223": "Will you be checking code complexity, introducing smaller functions?" "5263": "Did you set up a Kickstarter?" "5288": "Wouldn't it be nice if tiles were 1.0m instead of 1.4m?" "5333": "Closing thoughts" --- name: "day034" title: "Tile Map Memory" markers: "0": "Intro" "278": "The more you know" "505": "Time to program" "570": "Adding smooth scrolling" "742": "Scrolling works - next test code from yesterday" "840": "Change position offset to be from the tile center" "1035": "Calculating new tile from center offset (discussion)" "1330": "Implement tile offset from center" "1690": "Player moves faster for testing" "1793": "Make a larger world" "2200": "Start creating a new tile map procedurally" "2610": "Persistent game storage" "2990": "Size type" "3870": "Going for it" "4150": "Fate" "4260": "Summary of the day" "4480": "Q&A" "4565": "Garlandobloom says hi." "4578": "Can you explain the motivation behind controlling the page granularity." "4955": "Is the memory arena for more temporary objects than we're storing in the game state directly?" "5130": "Why not have smooth scrolling?" "5180": "We already have the -Oi compiler flag set." "5372": "Does using the memory arena still allow you to hotload your code?" "5491": "Will we be implementing our own trig functions?" "5520": "Will there be enough memory to store the entire sparse tile map?" "5563": "Why not just allocate a large 1D array?" "5740": "You're using a lot of pointers here. (Rant)" "5973": "Will the memory arena be aligning the assigned memory?" "5992": "Don't forget to disable -O2 again." "6005": "Comment on calling sin/cos for x86" "6057": "Why don't you use lookup tables for sin/cos (Rant)" "6162": "How can you say you don't need to free up memory?" "6208": "Is memory access slower than MOV?" "6285": "Why are tiles used? What is the real benefit of tile mapping?" "6362": "Remark on x87" "6392": "Conclusion" --- name: "day035" title: "Basic Sparse Tilemap Storage" markers: "0": "Intro" "130": "Making some rooms" "210": "Making some doors" "319": "Lots of small rooms and Tile ID values" "525": "Now you can see the limits of the world" "560": "Make rooms only in some places - Random Numbers" "660": "Yangtian Li's Talent" "703": "Back to random map generation" "1638": "Not sparse yet" "2010": "Making doors" "2467": "Going back to display single room" "2653": "Tile map review" "2930": "Adding the ability to go up and down" "3410": "Continue the madness and add some stairs" "3830": "Up and down" "4020": "Q&A" "4062": "Would you use DeMorgan's Laws?" "4218": "Do you have emacs commands with Visual Studio?" "4245": "Have you already decided what PRNG algorithm you're going to use?" "4262": "As you put the tile map in 3D dimensions, could this be related to a voxel octtree algorithm?" "4458": "Is there a reason for the chunk size to be a power of 2?" "4594": "When do you use #define instead of local variables?" "4752": "Why are you using inline in variables?" "4770": "Why not use bit flags for floors and such?" "4814": "Why would you prefer an array of tile chunks?" "5070": "Are you following Robert C. Martin Rules?" "5080": "Are we planning to load/unload tile chunks on demand?" "5140": "How much of this code will be used in the final procedural generation?" "5186": "Are we planning on making the tile map layered?" "5222": "Microphone question." "5235": "Why suffix types with 32 such as bool32?" "5315": "Will we need compression for basic sparse tilemap storage?" "5358": "How computationally expensive is the sparse storage?" "5592": "Should rooms only be created when the player is close to them?" "5941": "Are you worried about memory leaks?" "5971": "Are ternaries bad?" "6002": "Why is not possible to save the full map?" "6025": "Conclusion" --- name: "day036" title: "Loading BMPs" markers: "0": "A recap of previous stream" "125": "New test assets for Handmade Hero project" "286": "Introduction to loading BMP files" "388": "Handle player moving up and down 'stairs' before the BMP loader" "560": "Context-switch cost" "646": "Moving up an down implementation" "885": "Difference between tile map system and tile map positioning system" "954": "Implementation continued" "1033": "Fixing generation code" "1305": "Generation code fixed" "1358": "Implementation complete. Working tile map system" "1507": "Loading BMP files" "1590": "A talk on the game's screen resolution" "2170": "Implementing loader" "2360": "Crash course on how to read file formats" "2638": "Debugging a BMP file in memory" "2940": "Processing the BMP file header" "3043": "Packing a struct to avoid padding" "3233": "Processing the BMP pixels" "3560": "Q&A" "3584": "Perfect pitch would sell that!" "3658": "I missed the part where you handled the endianness of the file, or are bitmaps always the same?" "3716": "Do you prefer #pragma pack or gcc-like annotation?" "3748": "What's your threshold for number of function parameters before putting them into a single structure?" "3797": "Could you please describe how the sparse tilemap storage is done so far?" "4273": "Why not use a function template to read raw bytes into any struct you cook up, one primitive at a time, instead of compiler annotations?" "4499": "How will we handle memory when reading files? Would it be wasteful to read into our memory pool, then only use part of it?" "4601": "Could you explain how to handle platform specific data?" "4796": "Would it be easy to implement a generic sparse array to solve our tilemap problem (possibly overloading)?" "4862": "So we have world chunks and -tiles, didn't we also have screens?" "4905": "Why wouldn't you use a function template in the example mentioned before?" "5231": "Will you write asset exporters/importers to get the assets into an efficient format or will you rely on the asset creators tools?" --- name: "day037" title: "Basic Bitmap Rendering" markers: "19": "We're goin' in" "130": "Recap on where we are" "252": "Debugging image file formats 101, creating structured art" "537": "Viewing the structured art in the debugger" "695": "Changing the art to give better information" "818": "Reverse engineering the byte order" "1015": "Why to know how to do this" "1149": "Shifting the alpha values to align with our pixel format" "1339": "Top-down vs bottom-up and filling the backbuffer" "1754": "Loading the actual test art" "1915": "Return relevant information about the bitmap" "2092": "Loading hero bitmaps" "2707": "Displaying hero bitmaps" "2770": "Debugging busted hero bitmaps" "3788": "Getting more info from the bitmap headers" "4057": "Q&A" "4090": "Stream spots a typo" "4120": "Stream spots another typo" "4149": "Will we stick to using bitmaps for the duration of handmade hero, or delve into the lands of PNG?" "4219": "What's the advantage to defining the bitmap header yourself instead of using Windows's?" "4264": "Are we converting our loaded images to a runtime texture format?" "4300": "Why not use a simple custom format for assets?" "4310": "PNG is lossless" "4357": "Are you going to do different blending modes than alpha blending?" "4450": "Should asset loading code be in the platform specific or independent code?" "4503": "Correction to alpha blending question: sub-pixel rendering" "4772": "When we get alpha blending, will we think about gamma correction?" "4837": "Will we be doing resampling to get bitmaps on screen with arbitrary sizes?" "4856": "Will Handmade Hero have Mordenkainen's faithful watchdog?" "4895": "Cool command line texture is homemade" "4903": "Are bitmaps going to be in an atlas file? *reminder on what kinds of questions to ask*" "5008": "I saw a height * (width - 1), should that have been (height * width) - 1?" "5216": "In tiles code, will the area where it's possible to move be imported in bitmaps too?" "5276": "You can simplify DrawBitmap() by changing MaxX initialisation to MinX+Bitmap->Width, same for height" "5340": "Why not embrace the inverted bitmap format?" --- name: "day038" title: "Basic Linear Bitmap Blending" markers: "0": "Prestream stuff" "558": "Intro and welcome" "652": "Where we left of from last time" "677": "Fixing the hero's color" "976": "Figuring out what the shift values are" "1128": "Bitscanforward" "1673": "Renaming bitscanforward to FindLeastSignificantSetBit" "1776": "The intrinsics thing" "1816": "Finding out what compiler we're on" "1887": "Making a comprimise: Allowing the intrinsics file access to the platform layer" "2000": "Determining what compiler is being used" "2480": "Simple version of using the alpha channel" "2720": "Alpha as an opacity value" "2796": "Implementing 0-128 off, 129 onwards on for alpha" "2960": "The dumb, slow way to do alpha blending." "3004": "Krita crashes.." "3047": "Blackboard session explaining alpha blending using the background value" "3061": "'Deriving' the formula for a linear blend" "3482": "The cannonical form of a linear blend" "3525": "How the 't' works in the linear blend formula" "3635": "Implementing the floating point version of linear blend" "4015": "Drawing the herohead at the location of the player" "4043": "Q&A" "4086": "Stream spots a typo!" "4117": "Stream suggests to assert the bitmap assertion mode!" "4152": "You do not need #pragma intrinsic if you include " "4253": "Would it be worthwhile to avoid converting to float while doing the alpha blend?" "4366": "Why is the Windows-logo still visible at the top?" "4451": "Are there other ways to alpha blend and should you be taking into account which colors are easier to see?" "4866": "Are we at all concerned with the destinations alpha?" "5128": "Will the final blend favor the source over the destination, or is linear good enough?" "5159": "How would you deal with other picture formats such as png, jpeg, etc." "5213": "Why is the mask so complicated to use?" "5271": "Did you mean the other compiler LLVM or Clang?" "5317": "In the bitscan function what about returning index negative one if not found?" "5344": "Can you go over the linear alpha blend diagram again?" "5676": "Is the large VirtualAlloc() at the beginning similar to Linux mmap()?" "5751": "What bitvalue is 50% brightness?" "5854": "Does the display bitmap operation actually do anything with the alpha channel?" "5878": "The solid curve on Wikipedias gamma correction is the linear space intensity. Should be what you're looking for." --- name: "day039" title: "Basic Bitmap Rendering Cleanup" markers: "0": "Intro and Welcome" "295": "HeroBitmaps structure" "338": "Loading all hero bitmaps" "483": "Drawing loaded bitmaps in the correct order" "572": "Update hero by facing direction based on movement" "701": "Centering the hero on his rectangle" "860": "Finding the center of alignment" "928": "Drawing the bitmap based on alignment" "1055": "The bitmap-changing macro" "1209": "Changing DrawBitmap() to be based off of top and left alignment" "1409": "Explanation of how to draw hero based on alignment" "1545": "Changing the game such that the camera stays centered" "1630": "Adding the camera's position" "1785": "Computing where the player actually is" "1936": "Tile map difference" "2036": "Accounting for the AbsTile" "2230": "Fixing the movement" "2425": "Moving the camera to the player in Z" "2469": "Keeping the camera locked to the player" "2845": "Fixing left and top clipping" "2895": "Explanation of how to fix clipping" "3100": "Checking the framerate" "3158": "Fixing live code loading" "3569": "Testing if hotloading is still functioning" "3635": "Q&A" "3706": "Can you do that live code with a function call? That could just be a poke. -Geneticspecies" "3725": "Enumerations. Am I correct to say you've not used them in Handmade Hero yet? I'm guessing this is simply because it's too early to know what will eventually require enumerations and not some other reason." "3758": "Why not layer the individual bodyparts into a single bitmap that way you only have to draw one image instead of three?" "3800": "Are you wearing a blue cape like the Handmade Hero today?" "3811": "I just wanted to point out that there is a magnifying tool in windows that came with aero" "3909": "Don't you want to test the hotloading? -Andysz" "3939": "HAHA YOU SWORE! -Garlandobloom" "3967": "Can you add a include to handmade.h?" "4076": "Why does the guy have no feet?" "4097": "How do you know which compiler options, like clr and standard headers, you want to use?" "4246": "Changing the literal value of a variable is a peak and poke technique. Poking a value to a memory address..." "4403": "What will happen if you have an item that is infront in one view but in the back in another? Since it seems you have hard coded the order in which they are drawn, will you reorder them based on the view or on some other technique?" "4490": "Why don't you use the emacs calc?" "4525": "Comment on zoomin being at sysinternals.com" "4594": "When you panned off the min edges can you explain how the head was redrawing over the body?" "4922": "Do you ever write test or does the average game not have unit tests?" "5014": "Does this form of live coding work with adding member variables to structs?" "5064": "How does this test code help with the future architecture since it all gets dumped?" "5165": "I'm not sure if this is true. I'm assuming you're making the guy clip when leaving the screen, but why make it clip if you can just make it follow the yellow box which might clip the guy itself. Again I really.." "5195": "If streaming assets will be required to display all visual information will their be some type of manual limit placed on the procedural generation to ensure that all assets will never be required for a single room?" "5220": "End Q&A and closing statements" --- name: "day040" title: "Cursor Hiding and Fullscreen Support" markers: "3": "Intro and welcome" "130": "What we're going to do today" "210": "Cleaning up tSine" "233": "The reasoning behind internal, local_persist, and global_variable" "576": "Searching for static" "594": "static_check.bat" "880": "Cleaning up the TODO(casey): list" "980": "Tackeling SetCursor" "1065": "Spy++" "1305": "LoadCursor()" "1550": "Setting up dynamically controled cursor visability" "2052": "Trying to figure out how to stop the 'loading' cursor" "2273": "Fullscreen support" "3069": "Discussion on his method of going fullscreen in Windows" "3285": "Going over the notes" "3330": "'Hackey' way to fill the entire screen with the game" "3530": "Q&A" "3597": "You said you want your artist to leave an alpha apron around your bitmaps. Why is that?" "3735": "Sour trolli worms or Haribo gummy bears?" "3756": "We've got a fair bit of if statements that clamp values. Would a macro make sense?" "3806": "Why do you size of the variable and not the type for MonitorInfo()?" "3878": "Do you prefer separate files for sprite frame elements or a single sheet of them?" "3986": "My asserts in RecanonicalizeCoord() fire up often. Is it a problem?" "4038": "Is supporting different screen sizes part of the plan? (aspect ratios)" "4106": "Could you explain how transient memory storage works?" "4144": "How would you implement a vector? Would you use macros, metaprogramming or something else" --- name: "day041" title: "Overview of the Types of Math Used in Games" markers: "0": "Intro" "118": "Discussing the reason for a math discussion." "238": "Overview of math in programming" "500": "Arithmetic & Algebra" "607": "Euclidean Geometry" "755": "Trigonometry" "842": "Calculus" "1092": "Complex Numbers" "1198": "Higher-level mathematics in game programming." "1249": "Linear Algebra" "1762": "Partial Differential Equations" "2039": "Ordinary Differential Equations" "2463": "Non-euclidean Geometry" "2884": "Topology" "3080": "Minkowski Algebra" "3234": "Control Theory" "3302": "Interval Arithmetic" "3420": "Graph Theory" "3512": "Operations Research" "3588": "Probability & Statistics" "3610": "Discrete mathematics" "3753": "Q&A" "3791": "Do you even breathe bro?" "3800": "Doesn't toroidal topology also apply to spheres?" "4078": "Laptop battery dies" "4207": "Q&A Resumes" "4236": "Is it important to clarify many of these subjects can be learned when you need them, not needed as a baseline?" "4301": "Most of 3D games is in euclidian geometry" "4345": "What happens in partial differential equations if Scott Meyers is in a gorilla suit.." "4403": "Don't the tiles near the inner part of the torus get smaller compared to outside?" "4559": "How is dealing with complex numbers in four dimensions more useful for doing rotations?" "5079": "Ever do anything with laplace transforms?" "5136": "What type of math is used in AI?" "5165": "Is all of the things shown in math classes useful?" "5221": "Quaternions as you use them in rotations are not euclidian!" "5257": "Can we talk a bit about what out of the master list do we expect to use in this game?" "5325": "Will the next two weeks cover the basic functionalities of the parts that are math heavy?" "5362": "Did you learn most of your math from books or did you take courses?" "5377": "I heard Markov chains are also useful crossing control theory with probability. Will we use these?" --- name: "day042" title: "Basic 2D Vectors" markers: "0": "Intro" "22": "Character movement code." "105": "Recap" "170": "Issues with current character movement code." "265": "What we want to do with the movement code." "293": "What makes a game engaging." "390": "Reason for vector math." "420": "What to start fixing." "455": "Vector math intro." "696": "Sketches" "1146": "A scalar problem for the viewer." "1493": "Correcting player's diagonal motion." "1570": "Transitioning to vectors." "1830": "Vector notation" "1993": "Basic Vector Operations" "2266": "Multiplication in Vector Space" "2610": "Adding vector routines to the code" "2905": "Replacing scalar code with vector code." "3713": "Q&A" "3748": "How do union types work in C++ and what are the drawbacks?" "3882": "About vector conventions" "3907": "In the first version of vector, weren't you just missing an anonymous struct in the union?" "4043": "How do you remember all these commands?" "4127": "Is there a performance reason not to use constructors for v2?" "4216": "When would the fact that objects members are private or public come in to play?" "4324": "You should be able to have compound assignments outside the object." "4442": "If you're using vertical bars for vectors, how would you notate the determinant?" "4442": "If you're using vertical bars for vectors, how would you notate the determinant?" "4523": "Can't you make the whole vector struct an union?" "4590": "Does the altered v2 work now if you comment out the constructor?" "4689": "What libs are you using?" "4697": "Just tested the v2 struct in llvm and it compiles fine." "4720": "If I remember correctly, both gcc and llvm complains about the union struct" "4773": "Do you have any book recommandations for vector math?" "4934": "Will you define vector and scalar addition?" "5115": "Any particular reason to not supporting both vector-scalar and scalar-vector operators?" "5179": "The earlier struct-syntax is C99" "5197": "Does not returning real32 instead of v2 in *= operator trim your y-value?" "5305": "In C++11 you can do (v2){5, 2} as v2{5, 3}" "5383": "Don't you need some graphics library to place stuff not in a console?" "5480": "It's time to upgrade your copyright notice!" "5539": "Do you have use for constants like v2up, v2down etc?" "5630": "Copyright should cover all years in which content was contributed" "5688": "How about adding const references to function parameters to avoid copy by value" "5753": "Doesn't const help the compiler optimize?" --- name: "day043" title: "The Equations of Motion" markers: "62": "Intro to equations of motion." "173": "Recap of yesterday's stream." "308": "Motion in-depth: rigid body dynamics." "555": "Linear dynamics." "833": "Fundamental equation of motion." "1075": "Revisiting vectors." "1430": "How we computed motion." "1535": "Some calculus." "1737": "Computing motion differently." "2191": "How it's currently done in the code." "2230": "How we want to change it for our new equations." "2417": "A talk on delta time." "2566": "Piece-wise functions." "2615": "Implementation." "2953": "A look at the game now. We notice player has no friction." "3082": "Implementing some friction." "3506": "Closing remarks." "3640": "Q&A" "3683": "Why use real physics and not something custom you can handtune?" "4019": "Why not add an opposite directional deceleration when collisions occur?" "4049": "Are you concerned that actual physics will retract from the beauty and elegance of the worlds greatest jump code?" "4086": "What would you need to store if you wanted to rewind time ala Braid?" "4373": "Is the character a bitmap?" "4402": "Are we going to normalise the vector from the input, instead of having a special case for diagonals?" "4441": "Will there be a map function to help determine terrain for friction and collisions?" "4477": "Why v2 instead of vec2 or vector2?" "4513": "Why not break the code into smaller functions?" "4596": "Shouldn't you use a max speed variable?" "4652": "Someone: Friction negative acceleration based on current velocity would feel better" "4686": "Can you derive the 1/2at^2 part of the position equation again?" "5034": "Do you think something like bullet or box2d for player movement is appropriate?" "5138": "When would you use other integration methods?" "5660": "Will we use rigid body even after the hero is bouncy and all that?" "5700": "Correction on question from someone" "5749": "If we had terrain (ice or mud), we could have an easy convincing example" --- name: "day044" title: "Reflecting Vectors" markers: "33": "Importance of vector math" "129": "Recap of last episode" "216": "On the homogeneity of scalar and vector math notation" "345": "Goal for today: bouncing off of walls" "426": "Blackboard diagram of expected bouncing behavior" "467": "Axis-aligned vector reflection" "746": "General-case vector reflection" "902": "The inner/scalar/dot product" "1421": "Applications of the inner product: vector length" "1635": "Applications of the inner product: measurement of vectors on new reference frames" "2062": "Solving general reflection using the inner product" "2424": "Implementing the solution" "2602": "Placeholder code to detect orientation of colliding walls" "2959": "Short comment on loss of energy and coefficient of restitution" "3025": "Challenge to the stream: how do you run along the wall?" "3111": "Answer to the challenge" "3208": "Discussion on sticky behavior" "3493": "Q&A" "3571": "Can you explain again why the hero was sticking against the wall?" "3763": "When do we scale down the hero?" "3791": "Have you considered using sin(0) to sin(90) as a non-linear inertia curve?" "3831": "Will you eventually handle player and monsters in some kind of physics engine?" "3872": "Do you need to code in different collision detection for the enemies?" "3909": "Will you add comments to the source for those who preordered?" "3945": "Do you plan on having non axis-aligned walls in the maps?" "4032": "What do you think about position based dynamics?" "4122": "Are we going to do continuous collision detection?" "4148": "Is the computational cost of functions something you only learn by experience?" "4268": "Will you end up in problems when walking into corners after the sticking fix tomorrow?" "4287": "Will there be a minimum distance to the wall?" "4323": "Will computing a vector where the player will stop just before the wall solve the sticking?" "4393": "Additional explanation to the bounce vector calculation" "4765": "Is there a way to speed up the DrawBitmap -code?" "4875": "Suggestion to remove reblitting the background to improve performance" "4928": "Stream notes Casey drew the cos/sin triangle wrong" "5019": "A wish to mention formal keywords to help people look things up" "5093": "Was the Witness collision trick to try maintain the distance traveled?" "5121": "Why does wall bouncing not seem to cause sticking, but sliding does?" "5226": "Stream mentions KhanAchademy for learning math" "5240": "Will the rendering code be able to squash bitmaps?" "5281": "Could you/would you benefit from unrolling the collision loop ... ?" --- name: "day045" title: "Geometric vs. Temporal Movement Search" markers: "0": "Intro" "88": "Recap" "150": "Sticking problem recap" "254": "2 ways to handle problem: search in T, search in P" "560": "Problems with search in T" "676": "Solving the problem The Witness way" "930": "Problems with search in position" "1102": "How to implement search in P in Handmade Hero" "1315": "Why you need a flood fill" "1348": "The problem with players with volume" "1690": "Implementing search in P" "1885": "Breaking apart code" "1960": "Casey on messy code (rant)" "2155": "Simplifying the movement code" "2310": "Problem with unsigned integers on the zero boundary" "2417": "Finding the closest tile for each loop" "2525": "Check for empty tiles" "2695": "Defining the valid player region inside the tile" "2840": "How to perform the search" "3360": "Getting the length of a vector" "3460": "Cleaning up to finish on day 46" "3527": "Q&A" "3601": "Why different versions of GetTileValue()?" "3837": "You start variables uppercase and structs lowercase. Why?" "3887": "When npc's are introduced, will they reuse some of the code shown here?" "3954": "Are you going to implement push/squeeze through doorways?" "4051": "It seems like the possible movement is more like a pizza-slice?" "4116": "How would we, using this system, handle when the player would be killed by collision?" "4207": "Will we have to push boulders out of the way of doors?" "4224": "Will you ever fall for some of the dogmatic traps when coding?" "4391": "Does the search method here give the sense of rounded corners?" "4454": "I don't really understand this. Why not just change the players vector with normals?" "4581": "Are you going to worry about how many objects the collision detection system can handle?" "4692": "For search in p, don't you have a problem with passing through walls?" "4775": "Will the search code work if he hits a small notch that would make him bounce back?" "4875": "Will you implement secrets when none of us are watching?" "4940": "Will the characters have skeletal animations?" "5019": "Will the search in p work with moving objects?" "5120": "A great deal of the problems you've faced seems to be around tradeoffs.." --- name: "day046" title: "Basic Multiplayer Support" markers: "0": "Intro and welcome" "85": "Where we were.." "110": "Addressing a bug that was found by the forums" "270": "Thinking about how to handle imput" "384": "Which controller maps to which character?" "544": "How we're going to handle this problem" "636": "Maping a controller to a character" "696": "Pulling player info into the 'entity' structure to support multiple players" "770": "Modifying game_input to allow for multiple players" "871": "Changing his mind about how to handle this" "1139": "CameraFollowingEntityIndex" "1151": "Making the camera follow a certain player" "1327": "Drawing all of the players" "1478": "Fixing HeroFacingDirection" "1701": "AboluteValue intrinsic" "1771": "Adding an entity to the game" "1883": "Initializing a player" "2020": "Crash!" "2184": "MovePlayer()" "2364": "Moving player width/height into InitializePlayer()" "2535": "Calling the movement code" "2604": "Debugging the movement code" "2828": "Some days, you just have to fire yourself." "2946": "Fixing facing direction, again" "3042": "Retuning movement constants" "3129": "What we're going to do tomorrow" "3180": "BRB, controller!" "3239": "Demo of mult-player support" "3270": "Q&A" "3308": "On split-screen what kind of resolution were you thinking for each?" "3375": "You once said visualizing problems is never a wasted effort. Should we use it for collision detection?" "3412": "Are entities just for players or all game objects?" "3443": "How input be handled when both players trigger an action at the same time?" "3466": "Who is the camera following with multiple players? [code change]" "3644": "When you decided to have multiple players you decided to call them entities. Why?" "3716": "How do you make the characters not run through the trees?" "3830": "Why are we doing physical based movement?" "3877": "Will we be doing any image manipulation with code?" "3887": "Any reason to catch failing to load art assets? [code change]" "4014": "Is the notion of having all entities in a single array something that'll stay for long?" "4042": "Why do you not use an auto-compiler?" "4071": "How would disconnected controllers mid-game gracefully handled?" "4133": "When comparing a float to zero shouldn't we be checking withing a tolerance instead?" "4166": "Will there be diagonal movement sprites to the hero?" "4229": "Since small velocities were brought up, will we account for small inputs i.e. deadzones?" "4321": "About storing entities in an array. If there's massive operations on many of them, can this be exploited?" "4383": "Why didn't we use the bitmap masks directly?" "4522": "Are there any games that you've personally developed that are available to the public?" "4659": "Why do you use the function call macros?" "4713": "Will you wait for Jon to finish his presentation tomorrow?" "4734": "Can you explain what you mean by 'deadzone on the controller'?" "4974": "Do controllers have an outside deadzone?" "5038": "Addition to bitmap loading question: 'You && with a 32bit value and use what you get'" "5191": "Can you ever talk about the code you made that shipped 2000+ times?" "5280": "Will we be using a component system?" "5300": "Any estimation where GUIs will appear?" "5335": "Chat says: there are rotation instructions " "5585": "[code change: Using rotation instructions]" "5985": "Rotate will work but it's microcoded, so don't use them if you want performance" "6016": "Doesn't the rotate mess with the XP compatibility?" "6054": "Pondering about microcode speed" --- name: "day047" title: "Vector Lengths" markers: "0": "Intro" "93": "Recap" "170": "Diagonal move recap" "280": "New analog stick problem" "633": "Changing vector length without changing direction" "840": "Doing it aggressively" "948": "An important note about ratios and squares" "1107": "Why use length=1?" "1210": "Back to the wall sticking problem!" "1296": "Explanation of search in T implementation" "1567": "Equation for search in T" "1777": "Simplest possible case" "1940": "Division by zero" "2157": "The equation to solve for infinite vertical and horizontal walls" "2235": "Fixing equation for finite wall sizes" "2310": "Implementing the new collision code" "2440": "How to find the tiles to check" "2750": "What to do about multiple wall collisions" "3253": "Q&A" "3325": "Why did you change from search in p to search in t?" "3572": "How does it handle the state of two separate players on different floors?" "3618": "Why is the code complexity for p-search so much bigger than t-search?" "3799": "Why not treat the map as a matrix and validate objects and collisions through coordinates?" "3863": "Can you elaborate more on how the coordinate system works with the collision detection?" "4011": "Can this be extended to 3D collision?" "4024": "Could you check the player position and check if it's in the inner side of the wall vectors?" "4242": "What's your point on zero-length vector normalization?" "4374": "How come sometimes players can glitch through walls or corners? Is it art or programming?" "4624": "Do you need to do the math with solid walls and objects or is it basic program arithmetics?" "4722": "Chat adds: I think he means graphically. Walls can be hollow inside." --- name: "day048" title: "Line Segment Intersection Collisions" markers: "0": "Intro" "83": "Recap" "175": "Continuing yesterday's work on collision detection" "416": "Writing the wall intersection detection" "638": "Fixing backward movement" "722": "Fixing divide by zero" "860": "Actually move the player" "1088": "Description of partial wall penetration" "1140": "Adding the remaining wall tests" "1388": "New problem: walking through the top wall due to floating point precision loss" "1527": "Implementing a temporary fix" "1755": "Looking for another bug causing the character to stop early" "1806": "Debugging an assertion failure" "1970": "More collision bugs; time to write a better collision detection system!" "2018": "Observing the problems with the current collision detection system" "2125": "What we want from the new system" "2606": "Q&A" "2633": "Can you change the whiteboard colors?" "2793": "Do you plan on getting into calculus to get better collision detection?" "2825": "Do you think any need to prototype some features in some other language?" "2863": "If we changed the resolution of the game, would it change the size of the objects?" "2905": "Can you do collision detection based on if a bitmap and a pixel has alpha?" "3075": "Is it interesting to have a tutorial on floating-point computations?" "3125": "Why not use the old collision system and use the new one only if it finds a collision?" "3183": "What about the tiles? Will they stay the same if you change resolution?" "3293": "What is dynamic loading? I thought C code has to be compiled." --- name: "day049" title: "Debugging Canonical Coordinates" markers: "0": "Intro" "80": "Recap" "125": "Wraparound problem" "445": "Thinking about the problem" "909": "Changing the collision detection loop" "1545": "Why is X changing?" "1725": "Debugging all the things" "1880": "Fixed! The problem with RecanonicalizePosition" "2010": "Testing the new wraparound solution" "2250": "Fixing camera position" "2330": "Describing the camera position problem" "2560": "Changing topography from toroidal to disc" "2750": "Making the collision detection better using areas instead of points" "2880": "Fixing canonicalization" "3194": "Talking about the future of the tile map" "3410": "Q&A" "3489": "Do you use diagrams a lot in your actual work?" "3506": "What do you recommend for learning c++?" "3525": "Try setting handmade hero start at the midpoint between tiles" "3614": "What are your initial thoughts on DX12?" "3656": "Why is your code over 900 lines?" "3673": "How about using signed values for the top coordinates?" "3700": "Stream went offline" "3718": "Why don't you like private?" "3754": "Is there any background information you can give us new viewers?" "3779": "Do you see any complications broadcasting sound from float space in the next room?" "3923": "What is your preferred scripting language?" "3937": "I'm curious if you have to do with memory misalignment?" "3968": "Any reason you're making it somewhat more complicated than it should?" "4030": "How are you supposed to draw the game in Windows 10 without a HoloLens?" "4085": "Is the system rendering offscreen objects in the background?" "4111": "The struct name abc initialisation looks odd" "4155": "What's the estimated date for the release of Handmade Hero?" "4176": "Have you ever pair programmed?" "4187": "Do you go hard in the pain?" "4215": "Could you remove the old RenderWeirdGradient()?" "4230": "Why is there an issue with wrapping?" "4299": "Where did you get your education at?" "4308": "Does C handle pointers any different than C++?" "4335": "Do you use version control?" "4359": "Why not change the tilewidths and heights to 8x16 to wrap the camera with power of two?" "4435": "Can you explain how you use Minkowski addition in the collision?" "4519": "Are you eventually going to add tile entities?" "4575": "How much focus are you going to give to tile entities?" "4635": "How tall are you?" "4653": "What if you translate a 9x9 tilegrid to the player as origin before doing any world map?" "4688": "What do you use to draw?" "4729": "For wrapping you could just check if the new value is between uint_max and the nearest multiple of 9x17" "4751": "Can you explain what float-space is exactly" "5118": "Will you create a map editor?" "5134": "Seems like you could use bitfields or union to combine the different coordinates?" "5155": "What's the best way to learn how to code?" "5201": "I thought floats and doubles are the same speed in the FPU?" --- name: "day050" title: "Basic Minkowski-based Collision Detection" markers: "0": "Intro" "33": "Recap" "159": "To do today: Gliding/skating and area-based collision detection" "227": "Review of collision detection up to this point" "306": "Area-based collision detection (Minkowski sum/difference)" "415": "Example: A player with size passing through two blocks" "530": "Introduction of Minkowski algebra: algebra with shapes" "741": "Chumped by Krita" "924": "Back to the Minkowski sum: rectangle + circle" "1005": "Similar shapes" "1065": "Dissimilar & complex convex shapes: GJK algorithm" "1258": "Rectangles-only collision detection" "1555": "Taking entity size into account" "2025": "Sticky walls appear" "2165": "Changing the origin point of the player" "2280": "More sticking walls debugging" "2625": "Implementing gliding" "2880": "Correcting velocity during collision" "3370": "Debugging final sticking bug" "3640": "Moving the epsilon to stop directly on the wall" "3800": "Or not…" "3860": "Debugging first loop through the wall collision loop" "4198": "Debugging the second loop through the wall collision loop" "4685": "Moment of enlightenment" "4762": "Q&A" "4865": "Why is the heros head 1.5 meters in diameter?" "4889": "How would you handle concave objects with Minkowski?" "4961": "Why isn't the game split up in smaller, more modular files?" "5091": "Is the alpha channel in the art assets created by the artist?" "5121": "How many years since you started doing games?" "5197": "I usually just hope the framerate stays high enough for the velocity not to get too high" "5337": "Can't you have multiple views of the same file with emacs?" "5366": "Will you be able to use minkowski with rotating and diagonal objects?" "5610": "How long have you been working on this game?" "5637": "Is it possible to make an assert that lets you continue on failure?" "5657": "Are you doing any cyclomatic complexity analysis?" "5683": "How would you represent a large sidescroller 2D world?" "5743": "Is it possible to determine the point of collision?" "5771": "Seems like the inability to represent convex objects is a major for problem for physics" "5835": "I meant determining the point of collision with the general GJK algorithm" "5907": "Are we doing a Raspberry Pi port just for the heck of it?" "5964": "Cyclomatic complexity: a direct measure of the number of linearly independent paths through the code" "5990": "BeagleBone black is better than Raspberry Pi I think" "6061": "Can't you do straight on hardware on the PC?" --- name: "day051" title: "Separating Entities By Update Frequency" markers: "0": "Intro" "120": "Recap" "318": "What we're doing and why" "443": "The state of the world coordinate system today" "546": "The vision of the new entity system" "685": "Ballparking entity limits" "1098": "Scaling to large numbers of entities" "1245": "Low- & high-frequency entities" "1313": "Addressing other entities" "1510": "The initial approach for addressing entities" "1790": "Handling re-offsetting in local coordinate space when the camera moves" "2056": "Interaction between low- & high-frequency entities" "2145": "Updating code to add entities with different frequencies" "2440": "Implementing the inefficient version" "2585": "A note about split-screen camera" "2702": "Updating GetEntity to support different entity frequencies" "2933": "Updating InitializePlayer" "3125": "Updating AddEntity" "3265": "Getting the code compiling again" "3586": "Q&A" "3615": "How about hot/cold/frozen instead of high/low/dormant?" "3670": "Chat reminds: wrap intrinsic rotations [code change]" "3928": "Is it a good idea to update the low entities in a separate thread?" "3992": "In a dynamically based language how would you handle refactoring without the compiler help?" "4091": "I've noticed some game physics break when you increase the fps" "4223": "You're just shifting, not rotating [code change: shift-or rotate]" "4732": "Is there any gameplay reason why we want entities alive even off screen?" "4814": "About shifting negative values [code change]" --- name: "day052" title: "Entity Movement in Camera Space" markers: "0": "Intro" "100": "Recap" "192": "Thinking about removing the tile map and making tiles entities" "327": "Test entities against every other entity (O(n*n))" "377": "Update MovePlayer to perform collisions on active entities" "554": "Relative position between entities" "664": "Thinking about different actions for different types of collisions" "874": "Implementing walking on “stairs”" "1062": "Fixing compiler errors" "1168": "Implementing ChangeEntityResidence" "1320": "Thinking about entity types using a cache to keep high/dormant entity positions consistent" "1500": "An aside on programming technique (rant)" "1580": "Recalculating the position into tile space on entity update" "1766": "Mapping entities into camera space" "1900": "Exploring the code in debugger" "2120": "Changing residence of entities when higher residence is requested" "2370": "Debugging entity collisions" "2525": "Debugging sticky collisions" "2697": "Restoring camera movement" "3058": "Todos for tomorrow" "3203": "Q&A" "3253": "Why can't infrequent entity updates happen in the entity's update logic?" "3417": "Why do you want to use a 3D vector for position when the Z value is always going to be an integer?" "3685": "Does Minkowski collision detection have to be axis-aligned?" "3786": "Didn't you just implement a bare-bones relational database? Do you think that's a good mental model for understanding today's code?" "3957": "I noticed your characters do not collide with each-other. I thought you changed that?" "4028": "How good is this addressing scheme for the cache?" "4082": "When jumping you just need x, y, z coordinates to make it happen? [code changes]" "4583": "Will we switch to some kind of sparse storage for example for the high res entities?" "4614": "How would you handle jumping on a ledge or surface to adopt a new base height?" "4699": "What do you think about physics for character or mob movement in a platformer game, meaning that I press right but it starts to accelerate instead of just move?" "4756": "Now make him jump through the ceiling into the next floor." "4794": "Why is he so huge?" "4827": "Will the floor area of the zones be flat or will it have slopes and 3D zones a.k.a. hills?" "4929": "Can you change the yellow tile beneath his feet quickly and easily to be greyish and round so it looks like a jumping shadow? Completely not required but why not! [code change]" "5181": "If you add walls in the middle of rooms would they be handled as entities for the purpose of collision detection or separately?" "5224": "Too fast!" "5435": "How much has changing the rectangle to a bitmap instead of a rectangle impacted your player-on-player collision calculation?" "5453": "How many zombie DLCs will there be?" "5522": "Shouldn't you be doing this blending in a linear color space?" "5586": "When does the core mechanics of the game come into play? Earlier or later in the dev cycle?" "5719": "Is there an easy way to translate from circle to ellipse collision detection?" "5750": "Do you recommend learning to make a game engine rather than using engines like Unity or Unreal for people new to game development?" "5870": "The rectangle box which you have alpha assigned, is that the same box you would assign hit points to in case the character is injured by enemies or obstacles?" "5945": "How common or practical is pixel by pixel collision check vs overall shapes collision check? Which one is more interesting to you?" "5990": "What are your thoughts on the Allegro library?" "6000": "Stream end" --- name: "day053" title: "Environment Elements as Entities" markers: "0": "Intro" "82": "Recap" "162": "Fixing a crash reading off the end of a buffer" "705": "Making walls into entities" "865": "Pulling out camera movement code" "1076": "Removing entities from the high entity set that are too far away from the camera" "1160": "A note on pointer access" "1280": "A note on rectangle bundling" "1598": "Calculating the bounds of the high entity area" "1781": "Preparing to add entities to the high entity set that are close to the camera" "1989": "Putting wall entities in the tile map" "2048": "Changing InitializePlayer to AddPlayer" "2143": "Adding AddWall function" "2349": "Adding the walls right away instead of waiting for the collision detector" "3013": "Adding entities to the high entity set that are close to the camera" "3309": "Calling SetCamera at the start of the game" "3495": "Out of time! Where we'll start tomorrow" "3559": "Q&A" "3602": "Aren't some of the signs in the MinTileX wrong?" "3672": "What does “internal” modifier which is applied to the SetCamera function? I mean what is the difference between non-static and static function?" "4030": "Why do we consider a wall an entity?" "4107": "Will tile chunk and tile map structures go away and walls will be stored only as entities?" "4124": "We have to do some cool screen shakes and some whip pan transitions between screens." "4134": "Will there be a dormat enemy?" "4161": "Can we have some old man that transforms you into a dog and says “you're the dog now man”?" "4245": "Fixing calculation bug in collision detector [code change]" "4563": "What do you think of message buses and what is your favorite implementation of one?" "4580": "Are you planning on having any game screens that pan the camera?" "4635": "Have you ever played Path of Exile or heard of it? They have this desync problem that they claim is unfixable because they handle stuff server-side. Just wondering if you have heard of that game and its notorious bugs." "4677": "Are you using a stylus in Krita or a mouse?" "4698": "Does forcing a game to a certain refresh rate introduce lag?" "4748": "End" --- name: "day054" title: "Removing the Dormant Entity Concept" markers: "0": "Intro" "77": "Recap" "195": "Rationale for removing dormant entities" "356": "Ideas on decoupling low and high entity arrays" "623": "Creating things only in the low entity list by default" "940": "A note about the memory of the high entity array" "1298": "Thinking about using a free list instead of compacting the array" "1407": "Implementing array compaction" "1606": "Changing GetEntity to GetLowEntity and GetHighEntity" "1745": "Changing AddEntity to AddLowEntity and updating AddWall" "1856": "A note on refactoring/rewriting code" "1902": "Updating AddPlayer and MovePlayer" "2352": "Updating SetCamera changing residence from high to low" "2495": "A moment of clarity; description of trouble iterating over a mutating array" "2765": "Handling controlling entities" "3234": "Debugging crashes" "3350": "Debugging missing walls and positioning problems" "3728": "Q&A" "3792": "Is there an advantage of making the size of the LowEntity and HighEntity arrays a power of two?" "3862": "This is a third-person game right?" "3874": "What process would you have gone through for creating the controls and movement if this were a 2D side-scrolling platformer?" "3928": "Do you feel today will be rewritten during optimization?" "4000": "I don't know if it's been answered before but did you consider large fixed point integers for both entity types like Tom Forsythe seems to prefer instead of the swap between the floating point and the high frequency entities?" "4138": "Wouldn't be easier to keep a list of empty entity slots to add them there instead of always moving and changing one of the pointers?" "4191": "Are you familiar with slot maps for game object storage and do you think you'd use them for this project? We use them for our engine." "4282": "Any thoughts on controls for HH on controllerless touch screen devices like tablets?" "4347": "(follow-up) I think a slot map is just an implementation of handles doubly indirect referenced through a table." "4377": "Will Handmade Hero always be 20 scale feet tall?" "4386": "What are you drinking?" "4396": "(follow-up) What I call a slot map is an array that can have arbitrary empty slots and each slot has a version number for self-validation." "4520": "End" --- name: "day055" title: "Hash-based World Storage" markers: "0": "Intro" "125": "Fix typo in SetCamera" "180": "Recap of world coordinate wrapping problem & sparse world storage design" "617": "Introduction to hash tables" "916": "Hash functions" "1124": "Hash collisions" "1249": "Handling hash collisions: External chaining" "1516": "Handling hash collisions: Internal chaining" "1912": "Replace tile chunk counts with a hash table" "2184": "Creating the hash function" "2610": "Looking up entries in the hash table and creating new entries in the table" "2830": "Reviewing the code that has been written" "3480": "Moving the world origin" "3645": "Debugging missing entities" "4190": "Q&A" "4234": "Why not center the world at 0,0,0 and use signed ints for the tile position? [code change]" "4542": "Is a hash map essentially just a creatively shaped tile chunk? If that's the case could you preempt the hash function by contributing more bits from the Z coordinate as opposed to the X and Y for a towery map for example? Am I thinking about this right?" "4751": "What do you think about, and do you ever do, “free” optimizations in early or late stage development such as […] and instead trying to fail as early as possible? Best case scenario you only did one comparision rather than four." "4952": "What sort of cookie is best for programming?" "4960": "What do you think about splitting the hash map code from the tile code such that you can use hash map for other stuff later on?" "5112": "You're not passing the arena to the hash lookup function." "5146": "Is the world going to be generated on the fly or at game startup?" "5205": "Instead of chunks have you thought about spatial hashing? I'm considering it for my game to allow an open generated world but not confined to grid aligned tiles or fixed size objects." "5241": "What about using an octree for sparse style storage rather than a hash map?" "5433": "Since you are using a memory arena for all allocations how will you handle dynamic amount of objects like enemies, particles, etc.?" "5454": "Shouldn't the safe margin be INT32_MAX minus margin?" "5499": "When will this little guy have feet?" "5510": "Isn't the explanation where one letter points to the next letter until the end of the word?" "5593": "I think you said that a hash table was just one of many ways to store the sparse data. Could you briefly mention one or a couple of the other methods?" "5844": "Does starting at 0 cause a problem with the tile chunks since now we are using that as the uninitialized variable? [code change]" "5934": "Shouldn't Chunk->TileChunkX=0 be Chunk->NextInHash->TileChunkX? [code change]" "5974": "Will you write an analog function to malloc?" "6005": "(follow-up) I see. I guess what I was thinking about was what the full 4Bn x 4Bn map would look like if you passed each index in the hash map the opposite way through the hash function. It seems like it doesn't matter in any case becafuse no matter what it's always going to be better than O(n) and most of the time it's O(1) with a tiny bit of performance cost to throw the coordinates through the function." "6031": "Most of your comments are notes and todos. Do you ever add section title comments to separate long blocks of code?" "6053": "Do you see any value in adding unit tests for certain bits of this functionality?" "6103": "Can you visualize the shape of the map so I can understand why a hash table is better than an array?" "6280": "The randomized map only goes up and to the right at the moment. Is it good enough to catch bugs?" "6307": "Will the renderer be a separate piece of code as like the platform player so that it can be substituted with something like OpenGL?" "6318": "End" --- name: "day056" title: "Switch from Tiles to Entities" markers: "0": "Intro" "104": "Recap" "318": "Scaling low-frequency entity updates" "1005": "Revising the tile map" "1110": "Thinking about changing tile map to store entities instead of tiles" "1368": "Options for how to reference entities in memory" "1766": "Storing entities in tile entity blocks" "2012": "Thinking of a technique to improve low entity access" "2074": "Going in the other direction" "2169": "Removing invalid code" "2284": "Thinking about the size of the tile_map TileChunkHash" "2505": "Renaming tile_map to world" "3355": "Debugging refactoring" "3420": "Recap" "3517": "Q&A" "3539": "Do you still expect the gameplay to be broadly grid-based even without tiles?" "3584": "Could you use reflection to help handle the entities and world chunks?" "3653": "Will everything in the game be an entity even if it does not need collision detection or movement?" "3722": "Don't you think most of the storage concerns stem from having just high and low entities and would be solved by having more granularity there so you have more and smaller arrays of entities with some particular aspect?" "3767": "You mentioned considering having the world chunks store a fixed entity count and then add multiple chunks to the hash table if necessary to store more entities. If you were to go that route, how would you compare one chunk to another? Multiple chunks would have the same X,Y,Z." "3856": "In terms of handling entity compression and decompression, where would you grab/store the state of objects that are coming in and out of the update scope?" "3887": "Why do you call C compiled with a C++ compiler “C++”?" "3923": "Why can't world_position just have a pointer to a world_chunk instead of all those AbsTiles? Then Offset_ is relative to the world_chunk." "4044": "I didn't get to watch the entire stream so I don't know if you considered it, but why don't you have a flag for “about to be deleted” that every entity checks against and nulls pointers. Have it visible for all entities for one frame." "4107": "Do you think the todo puzzler will be handled tomorrow, and do you often sleep on decisions like that?" "4171": "(follow-up) What I was getting to is that we seem to be working towards what's called the Entity Component system where what we call now “high” and “low” are just components alongside anything else we want to add to entities later." "4238": "Seeing that the computer handles 1 million entities without lagging, do we really need to worry about the performance hit coming from one extra pointer dereference?" "4350": "Will entities be able to transfer from one chunk to another?" "4372": "Will we start using the entity system for something other than players/walls soon or will the renderer come first?" "4438": "End" --- name: "day057" title: "Spatially Partitioning Entities" markers: "75": "Recap" "191": "handmade.cpp: Create more rooms" "262": "Debugger: Inspect GameState while traversing the world" "440": "Consider creating a spatial partition" "655": "Blackboard: Spatial partitions" "839": "handmade_world.cpp: Introduce ChangeEntityLocation" "1093": "handmade_world.h: Rename AbsTile to Chunk and add ChunkSideInMeters to world" "1199": "handmade_world.cpp: Continue writing ChangeEntityLocation" "1356": "Discuss making FirstBlock a pointer rather than doing the block copy" "1502": "handmade_world.cpp: Continue writing ChangeEntityLocation" "1916": "Blackboard: Keeping the free space at the head of the list" "1990": "handmade_world.cpp: Continue writing ChangeEntityLocation" "2248": "Blackboard: Moving the final entry into the newly freed space" "2331": "handmade_world.cpp: Continue writing ChangeEntityLocation" "2535": "On spending time thinking about data structures vs memory management" "2598": "handmade_world.h and handmade_world.cpp: Manage the memory" "2811": "handmade_world.cpp: Update InitializeWorld and remove GetChunkPositionFor" "2889": "Update the sense of AreOnSameTile" "2946": "Introduce IsCanonical" "3126": "Continue cleaning up" "3358": "handmade.cpp: Change to using ChunkZ" "3413": "Introduce ChunkPositionFromTilePosition" "3514": "Write ChunkPositionFromTilePosition" "3732": "Unplug and plug the keyboard back in" "3783": "handmade_world.cpp: Finish cleaning up" "3854": "Q&A" "3939": "Q: Can you please go over the lasagne code again that goes through the linked list and moves around the entities? And can you remove the note in RecanonicalizeCoord about toroidal topology?" "4522": "Q: Are you dropping frames? Things are glitchy" "4551": "Q: Do you use Bink for videos?" "4577": "Q: For someone who does a lot of coding, nothing seems to be going your way today, including the stream integrity" "4593": "Q: What is your opinion on things like bunny-hopping or other movement mechanics that are bugs in the code, but contribute to gameplay, e.g. if there was a technique for getting speed in your game, albeit difficult? Would you keep it?" "4633": "Q: What do you think about namespacing functions like Entity_GetLocation instead of GetEntityLocation?" "4670": "Q: About PushStruct, isn't it true that it can actually fail if you are out of preallocated memory? So wouldn't you still have to check if your custom block allocation fails if your world gets too big?" "4744": "Q: Why do you need if(Chunk) after Assert(Chunk)?" "4766": "Q: Can you please explain, when you comment your code, what's the logic of having less comments on very big chunks of code?" "4897": "Q: When you said the code today wasn't that performance critical, I instantly thought about a machine gun - stone thrower battle just across a chunk edge" "4921": "We are done with questions" --- name: "day058" title: "Using the Spatial Partition" markers: "28": "Assets: handmade_hero_test_assets_002.zip is released" "121": "Recap" "208": "handmade.cpp: Pull in entities by chunk, rather than tile" "312": "Blackboard: Pulling entities into the working set" "526": "handmade.cpp: Figure out the CameraBounds situation" "925": "Make a version of MakeEntityHighFrequency to be called at the lower level" "981": "Introduce GetCameraSpaceP" "1061": "Continue writing these versions of MakeEntityHighFrequency" "1218": "Use these functions in SetCamera" "1301": "handmade_math.h: Introduce GetMinCorner, GetMaxCorner and GetCenter" "1372": "Debugger: Step through and see what's happening" "1454": "handmade.cpp: Fix the Assertion in MakeEntityHighFrequency" "1474": "Look at AddWall" "1551": "handmade_world.cpp: Look at Subtract and ChunkPositionFromTilePosition" "1604": "Debugger: Step in to AddWall" "1736": "handmade.cpp: Call ChangeEntityLocation in AddLowEntity and make it pass world_position P" "1829": "Pass the world_position P to AddPlayer and finish implementing the spatial partition" "2093": "Run it and see what's happening" "2159": "Debugger: Step into AddPlayer" "2207": "handmade.cpp: Tweak AddLowEntity" "2282": "Debugger: Continue debugging AddPlayer" "2317": "handmade_world.cpp: Tweak ChangeEntityLocation" "2380": "Debugger: Step through the loop in OffsetAndCheckFrequencyByArea" "2485": "handmade.cpp: Add an assertion in OffsetAndCheckFrequencyByArea" "2557": "Debugger: Step through and hit this assertion" "2614": "handmade.cpp: Introduce ValidateEntityPairs" "2756": "Debugger: The MakeEntityHighFrequency routine in SetCamera is the problem" "2824": "handmade.cpp: Pass the correct Index to this routine" "2885": "Run the game and note that the spatial partition is nominally working" "2928": "handmade.h and handmade.cpp: Test the new assets" "3040": "Run the game and find that the new trees are drawn at the wrong locations" "3064": "handmade.cpp: Stop drawing the textured background" "3171": "Assets: Find the base point for the tree in GIMP" "3217": "handmade.cpp: Set the tree's alignment and do DrawRectangle as well" "3272": "Run the game and observe our new trees in their correct positions" "3464": "Q&A" "3532": "Q: For zooming out, could you somehow modify MetersToPixels to make things smaller as you zoom?" "3579": "Q: What is inline v2?" "3664": "Q: Why use Emacs versus Visual Studio's IDE?" "3756": "Q: Is Emacs better than Vim, or is it just preference?" "3823": "Q: Do you think that how fast code runs is the best metric for good code, or do you value simplicity or extensibility as well?" "3959": "Q: Why are you using Visual Studio here if you use Emacs?" "3994": "Did you ever figure out a fix for Emacs whenever you try to create a new file and the patch changes?" "4023": "Q: What's guiding you to make steps towards completing the game, i.e. a list of requirements for the game?" "4134": "Q: Do you ever get annoyed with reading a high depth of nested for loops?" "4195": "Q: Was watching some ROM hacking earlier and watching the registers and memory update in real time was really cool. Do you think a debugger for C could work as well as that?" "4239": "Q: How much time do you spend outside the stream in thinking about the code and game design? If you coded eight hours a day, would you be able to code consistently with the same pace as during your stream?" "4298": "Q: Can you please put in a proper PRNG before you write world gen algorithms?" "4366": "Q: Do you ever feel the need to use recursive functions?" "4395": "Q: Do you build with build.exe in command prompt or batch file?" "4451": "Q: When you say "renderer", what exactly does that mean? If the drawing you have now isn't rendering, then at what point do we go from drawing to rendering?" "4555": "Q: Have any of your friends voiced disagreement with design decisions you've made in this engine?" "4582": "Q: How do you distinguish between what a lot of people might called "premature optimisation" versus ensuring a good design that allows for high performance? The difference there seems really subtle. I feel that designing for high performance is simply organising the code and writing in such a way that does not unnecessarily slow down the code and prevent future optimisations, while premature optimisation is simply optimising something because you think something will be slow without evidence" "4792": "Q: 4096 random numbers" "4803": "Q: Will we have positionless entities? Would something like the current price of Almond Milk futures be an entity?" "4822": "Q: Will you be making a level / tile map editor for this game, for easier level creation?" "4840": "Q: What is your algorithm for a collision with three and more entities?" "4881": "Blackboard: Moving in 1/30th sec" "4995": "Q: Do you plan to use some form of logging for debugging purposes?" "5028": "Q: When you remove a LowEntity from the Chunk list, you swap another into its place. Won't that mess with references?" "5055": "Even for slow frequency entities?" "5099": "We have come to the end of the questions" --- name: "day059" title: "Adding a Basic Familiar Entity" markers: "149": "Recap and plan for the day ahead" "334": "handmade.h: Add EntityType_Familiar and EntityType_Monster" "381": "handmade.cpp: Introduce AddMonster and update AddLowEntity" "649": "Add a monster" "724": "Run the game and see the monster" "817": "Reiterate the fact that it is the SetCamera call that brings everything into the HighEntity set" "869": "handmade.cpp: Write cases for drawing each EntityType" "1007": "Run the game and see our Monstar for the first time" "1030": "handmade.cpp: Add a familiar" "1096": "Run the game and see our Familiar for the first time" "1180": "handmade.cpp: Consider how to update the HighEntities" "1264": "Introduce UpdateEntity" "1350": "Consider the "jump code" and do some clean up" "1552": "handmade.h: Introduce entity_visible_piece and entity_visible_piece_group" "1672": "Change DrawBitmap calls to PushPiece" "2229": "Consider doing the rendering directly, rather than deferring it" "2286": "Finish implementing PushPiece" "2465": "Run the game and note that we're doing the exact same thing we were doing" "2478": "handmade.cpp: Add Update calls for the entities" "2542": "Compute the ShadowAlpha incorrectly for now" "2572": "Implement these Update calls and give the Familiar some logic" "2949": "Implement EntityFromHighIndex" "3082": "Change MovePlayer to MoveEntity" "3143": "Give the Familiar some movement logic towards the Hero" "3231": "Run the game and tweak the Familiar's logic" "3288": "Moment of realisation: The player's speed is baked into MoveEntity" "3304": "Make the Familiar move at half the speed of the Hero and check it out in-game" "3401": "Q&A" "3489": "Q: Why "Monstar" and not "Monster"?" "3538": "Q: If someone rewrites your code using OOP and it runs faster, what would you do?" "3564": "Q: Why do you want to be able to outrun your familiar? Doesn't having to stop for him to catch up get annoying?" "3644": "Q: Could you make the head bob up and down while following the player?" "3829": "Q: Could you write Pong real fast, so I can see how to start?" "3843": "Q: "Monstar" would be confused with "Mon*", a pointer to a Mon" "3859": "Q: Are we going to eventually use a component-based entity system, instead of using an enum of entity types? If not, why?" "3950": "Q: Would you think about doing some proportional integral derivative control for familiars to follow?" "4010": "Q: I have a bad feeling about that switch on EntityType. Do you think it will probably go away as we get closer to the final architecture?" "4055": "Q: Would collision be an XY-only thing, or would you take into account Z, as in jumping over another entity?" "4129": "Q: I have a feeling your Low entities will be quite big if they have AI and stuff. Won't this be a problem for the huge world? Maybe it would have made sense if you had kept the tile data in chunks so you can deflate some entities just when needed" "4187": "Q: The performance boost off the low / high shuffle: when will we see this come into play?" "4233": "Q: Could we spawn a ton of these floating head things?" "5446": "Q: How will the Z work exactly?" "5495": "Q: Will there be a flock system for all the floating heads following the Hero?" "5503": "Q: What kind of path finding will be implemented for High entities and how will they differ from faraway Low entities? And will Low entity NPCs who are always on the move really far away always resolve? It would be interesting to come across a very live world full of history, dead bodies, etc. due to constant AI acting, but would that be feasible?" "5539": "Q: How easy would it be to chain multiple bobbly heads to follow each other?" "5725": "Q: CameraTileY + OffsetY not OffsetX in AddFamiliar call" "5764": "Q: I was very glad to hear that you deem classes to be basically garbage. I spent too much time with C# trying to learn object inter-jugglery between them" "5779": "Q: About the chaining familiars, could each familiar check if the hero has a familiar already and, if it does, then try to follow the familiar instead?" "5804": "We've come to the end of the questions" --- name: "day060" title: "Adding Hitpoints" markers: "115": "Recap and plan for the day ahead" "226": "Describe the "sumo mandarin" still being eaten" "286": "Fix jump shadow" "433": "Modify shadow alpha on floating head" "643": "Reiterate the fact that PushPiece is in pixel space" "706": "Make the familiar stop a little way from the hero" "821": "Add Hitpoint to hero" "925": "handmade.h: struct hit_point" "962": "Should hitpoints themselves be entities?" "1038": "Draw those hitpoints" "1418": "Blackboard: How to center hitpoints around the guy?" "1770": "Implement the code to draw these hitpoints in the right place" "1845": "Change the Offset in PushPiece into meter" "2331": "Run the game and watch the Familiar bob heavily" "2343": "Reduce the BobSin multiplier" "2376": "Place the hitpoints in their correct positions" "2484": "Blackboard: Explain why hitpoints stick together" "2528": "Flip the y coordinate in PushPiece" "2600": "Unify PushPiece and PushRect" "2763": "Fix jump hitpoints" "2779": "Basic v3 and v4" "3116": "Explain why templates are bad" "3314": "Q&A" "3377": "Q: Isn't making a struct for HP is preprogramming a little?" "3468": "Q: Why not just use HitPointMax = 12 instead of dividing into 3 hearts and 4 segments?" "3504": "Q: I noticed the floating head was always behind the player. Are you going to go for a depth buffer approach or draw back-to-front to handle this?" "4056": "Q: Would it be entirely possible to completely reconstruct the current code by following every episode of the series without preordering the game?" "4088": "Q: Do you think that I, as a totally new person of programming, would be able to follow along with the pace you are working at, doing rapid changes to the code without sometimes telling us why?" "4151": "Q: Is there ever gonna be a moment of reflection at some point in the future where you provide a somewhat high level overview of the engine components we have been encountered so far, what they will provide and why we need them?" "4234": "Q: I think it would be really cool if you implement a smooth scrolling room-based combination" "4279": "Q: Is the translucent thing you were talking about hard to do on 2D UI? Do you write the UI in the same Z-buffer or is it separate?" "4371": "Q: Will you be implementing more memory handling code and, if yes, what kind of things?" "4498": "Q: If you do a bounding box, which is an inset X amount of meters / tiles from the room edge, you could use the collision of the player with the bounding box to start smooth scrolling to the next room, etc." "4536": "Q: How will we be handling resolution variance?" "4601": "Q: What kind of error handling / logging do you have in place now, and how will that possibly change?" "4655": "Q: Why are strings such a problem for so many engines?" "4665": "Q: How hard is it to port a 32-bit game engine to compile a 64-bit output client if the origin game splits executables to surpass the 4-gig cap?" "4710": "Q: Zelda had scrolling when you transition between rooms. Are you going to have something similar?" "4727": "Q: Would you mind giving a brief walkthrough of the memory management going on right now in the code from the game boot and forward?" "4941": "Q: Why is it impossible to resize a raster image and why does everything have to be rasterized for drawing? Why can't textures be vector-based?" "5091": "Q: Couldn't we build handmade.cpp and win32_handmade.cpp in separate threads? Is there a way to pipe the error messages in a sane way using the build.bat approach?" "5157": "Q: SWTOR does it (about 32-bit splits into 2 separate processes question)" "5214": "Q: Binding of Isaac does have scrolling between rooms, albeit a very quick transition" "5257": "Q: What is the drawing app we are using?" "5293": "Internet: Check out the scrolling in The Binding of Isaac" "5394": "We've finish up on the stream" "5399": "Save our giant drawing in Mischief" --- name: "day061" title: "Adding a Simple Attack" markers: "116": "Recap and plan for the day ahead" "367": "handmade.cpp: Pull out the code draws hitpoints" "484": "handmade.cpp: InitHitPoints" "704": "Use sprite "rock03" as the hero's attack region" "815": "Blackboard: Casey demonstrate how to zoom in and out in Mischief and decide to save the handwritten into the handmade hero directory" "875": "Blackboard: Talk about the difficulties we will encounter if we treat sword as an entity" "1316": "Blackboard: "Imagine"" "1846": "Implement the sword" "2311": "Bind "Start button" for jumping and arrow keys for attacks in different directions" "2422": "Make sure that we take our sword and launch it" "2635": "Treat sword as a low entity the whole time. Let the camera system force it into high" "2670": "Consider mapping entities into the high set if ChangeEntityLocation moves it into camera bounds" "2721": "Back to implementing the code to launch the sword" "2817": "Introduce some notion to represent whether world_postion is valid or not" "3096": "Run the game and find out that sword doesn't show up" "3164": "Start debugging" "3575": "Visual Studio is awful at being able to show you variables when they exit the scope" "3758": "Find out that the CameraSpaceP of Sword is completely garbage" "3823": "Make ChangeEntityLocation update the new world_postion properly" "4013": "Run the game to verify whether the bug is fixed or not" "4082": "Q&A" "4125": "What do you mean that Visual Studio is horrible at showing variables, and how are you programming in Emacs and running it in Visual Studio?" "4312": "When doing exploratory / experimental programming, I find it difficult to decide between seeing things through or switching to a different approach. There have been many times where I start off on a path and things are going great, but eventually I stall due to some unforeseen problem. Often, I spend a crazy amount of time thinking about how to solve / get around the problem, even in simple ways. Analysis paralysis if you will. Any suggestions? Literally, just keep on writing code, no matter how dumb it is?" "4808": "Will you handle the case where a sword and a monstar would hit each other but are moving toward each other so fast that they pass through each other without colliding in a single frame?" "4845": "Do you think "cheesing" - like making enemies invincible for 10 frames after being hit - is a game design sin, or just something you'd rather avoid?" "5053": "Why not just use the auto window?" "5118": "Is VC++ still better than open-source alternatives?" "5201": "What would you think about adapting the art style to be easier to implement, either at all or this early on. The trite example being for the sword collision you mentioned early on, what if you were to do something like: okay, the sword is going to teleport along the path instantly in one frame and some red line a bit like anime that would be persistent through a couple frames. Basically potentially fundamentally changing the art style with the purpose of getting things to run better. Are there any examples of something like this occurring that you might have heard of?" "5302": "Are you working on the RAD debugger, or will you try using it for HMH before the debugger is released?" "5334": "You always talk about the ways of programming when you started or when programming was at its prime. How can I, an 18 year old, know what it's like or get the knowledge you have about programming? Are there any books or languages or SOMETHING I can do to learn the old ways of programming? [see Resources]" "5520": "Why did you pick C++ of all things?" "5711": "Would there have been an easier language to program the game in?" "5856": "To be able to surpass C++ as the defacto language to code games in, what would you have to do as a language that would make you better than C++?" "5897": "CAN I HAVE A WITNESS BETA KEY!!!" "5908": "Wrap it up for the day" --- name: "day062" title: "Basic Moving Projectiles" markers: "32": "Announce that we will save blackboard.art into handmade/misc/" "161": "Recap" "250": "handmade.cpp: Make the sword actually be thrown" "362": "Talk about the annoying and ugly entity usage" "485": "Back to implementing sword throwing" "567": "handmade.cpp: UpdateSword" "660": "For now only, turn off collision detection if the entity doesn't collide" "710": "Run the game and find out the sword is slowing down" "733": "Pull out move notions into move_spec and introduce DefaultMoveSpec" "1160": "Run the game and see the slow sword" "1175": "Speed up the sword and make sure the sword can only travel certain distances" "1529": "Run the game and hit the assertion" "1674": "An assumption of why we hit this assertion" "1829": "Use a hacky way to solve this problem" "1906": "Try to handle this problem more sanely" "2156": "Run the game and find a strange bug with the sword's velocity being set to zero" "2180": "Start debugging" "3299": "Realize that the bug is caused by the hacky code Casey just wrote" "3371": "Run the game and do some hookshot things" "3411": "Explain how these hookshot things happen" "3624": "Q&A" "3661": "Owl of SHAME!!!" "3700": "Do you ever use gdb?" "3706": "Do you test more than just using asserts?" "3717": "Why did you create a struct for each vector type, instead of using plain float arrays?" "3864": "Do you think version control would help when you go off on a tangent for the stream? You can roll back hacks like that?" "3885": "Not a question but that hookshot thing actually looked like it would be kinda fun to play with" "3911": "Reminder: Bendable shot which allows you to change direction of the shot once" "3929": "What are your feelings on the vector multiply operator performing a dot product?" "3997": "Do you keep your assertions for release code? If not, at what point do you remove them?" "4020": "Why wouldn't you encapsulate each entity type into its separate classes?" "4101": "Correct, they use hadamard" "4126": "Did you add the quick-calc hotkey?" "4233": "Is XML fair game in this project? It's not a library, but it still might not be handmade enough" "4307": "Don't you feel that Low entities have already too much extraneous stuff in them and it would be time soon to split them, and also things like the sword might not need the low part at all?" "4430": "What will we do at 3PM PST when this game is finished?" "4519": "Are you happy with the current progress?" "4559": "More than memory footprint I was thinking about unwanted side effects, i.e. code that deals with the transfer of properties ends up triggering hard to debug shenanigans with the positioning etc." "4633": "Wrap it up" --- name: "day063" title: "Simulation Regions" markers: "25": "Recap on getting initial usage code down to avoid bad design" "123": "Design constraints for high/low frequency entities" "286": "Float precision problem for large worlds" "501": "Problem of scaling to large entity counts" "606": "Realizing the problem - wrong way to think about low frequency entities" "678": "Realizing the solution - simulation regions" "978": "Handling entities moving outside boundaries of simulation region" "1119": "Starting the code reorganization" "1173": "The sim_region struct" "1270": "How to alter SetCamera" "1316": "Ending simulation by mapping entities in a sim_region into low space" "1458": "Beginning simulation by mapping entities into a sim_region" "1572": "Simplifying entity structs" "1646": "More details on BeginSim" "1751": "Adding an entity to a sim_region" "2063": "Switching from camera space positions to simulation space positions" "2282": "Adjusting the entity structs" "2388": "Memory allocation for sim_regions" "2565": "Storing back to low entities in EndSim" "2745": "Deleting code that is no longer applicable" "2933": "Replacing SetCamera with getting a sim_region in the main loop" "3064": "Moving camera position update from main loop to EndSim" "3108": "Adjusting rendering for simulation regions" "3360": "Wrapping up for today - fixing compiler errors" "3550": "Q&A" "3586": "Recommendation for names - instead of stored entities you could have stasis_entity and stasis_region; for the high frequency, you would keep the sim_region and sim_entity." "3629": "Since we know that an entity's speed is bounded, couldn't we calculate a sim_region with bounds such that no entity can move outside of it during the frame? That way anything that the entity could collide with would be pulled into the sim_region?" "3749": "How many TODOs do you have?" "3876": "How will you handle the disparity in update rate between offscreen and onscreen entities? Does it matter?" "3940": "Will the sim_region away from the player cause large timesteps from the normal?" "3982": "I missed whether this new system is based around discrete rooms or integer mapped coordinates. If it's based on rooms, would it be trivial to think in coords instead?" "4004": "What will happen if your sim_region and player location are at the same place? Will it bug out?" "4091": "Why is the low-high frequency system so important? Isn't creating basic gameplay rules and AI interactions in a small world more in-line with your philosophy of doing the simple thing first?" "4414": "How will we update low frequency regions given the sparse nature of the world?" "4444": "Is there a major advantage to using 'fors' instead of 'whiles'?" "4510": "What will the entities that are not visible on the screen be doing? I can't really think of examples of things that need to be updated if they're far from the player." "4653": "How many low entities does it take to screw in a light bulb?" "4706": "For your sparse storage, why not store the (x,y,z) coords bit-shifted into an aligned integer to use it as a composite key into a dictionary or hash map?" "4801": "Do you approach design in a similar way to your architecture (i.e. exploration-based design, design sort of emerges itself organically, etc.)?" "4824": "Is multi-threading in the scope of topics for the project?" "4880": "If a far away room gets updated and the rooms around it are updated too, don't we have this recursive problem where the around rooms need their neighbor too?" "4949": "How much work would it take to turn the game you are making from a 2D world into a 3D world?" "4987": "To clarify my early design question, I just mean as far as your design decisions for Handmade Hero." --- name: "day064" title: "Mapping Entity Indexes to Pointers" markers: "93": "Recap of where we are with simulation regions" "118": "Reorganizing the entity structs" "305": "Updating code for sim_entity within low_entity" "497": "Setting the entity's StorageIndex" "667": "Moving entity stuff out of handmade.h" "691": "How to reference entities?" "879": "Creating an entity_reference" "960": "Populating an entity_reference in EndSim" "1072": "Loading from an entity_reference in BeginSim" "1320": "Storing an entity mapping in a hash table when adding an entity" "1404": "Functions for the entity mapping hash table" "1444": "Creating the entity mapping hash table" "1623": "Internal chaining for the hash table" "1707": "Implementing GetSimEntityFromIndex" "2265": "Implementing MapStorageIndexToEntity" "2364": "Loading entities recursively" "2654": "Addressing compiler errors" "2714": "Updating camera following code" "2934": "Addressing compiler errors" "3027": "Porting MoveEntity code to work with simulation regions" "3389": "Leaving notes for remainder of simulation region work" "3423": "Q&A" "3533": "Why don't you upload chat logs with videos somehow?" "3668": "There's a bug in your random number table. The numbers are limited to a range." "3735": "Could explain your naming conventions or explanations behind using them? I've never seen a style similar to yours - it seems inverted." "3844": "Do you want the stored entities to move like normal ones or simulate them? Like you mentioned stuff moving around with slower updates off-screen." "3921": "Maybe if you change your Twitch server? [in reference to dropped packets for stream]" "3975": "What is the point of high and low entity? Would it make sense to just have one?" "4033": "Can entities reference each other? Do you need to check for cyclic references?" "4143": "When is a ground-up rewrite warranted? How often do you just burn everything down and start fresh?" "4712": "What are your opinions of Scrum and Agile methods?" --- name: "day065" title: "Finishing the Simulation Region Change" markers: "36": "Recap on where we are with simulation region change" "235": "Creating a separate file for entity behavior code" "380": "Changing DrawHitpoints to operate on sim_entity instead of low_entity" "425": "Separating code for updating player from controller processing code" "1327": "Fixing more compiler errors" "1417": "TODO for renaming sim_entity to entity" "1463": "Fixing more compiler errors" "1503": "Bringing in handmade_entity into the build" "1523": "Fixing UpdateFamiliar" "1683": "Fixing UpdateMonstar and UpdateSword" "1778": "Overview of remaining TODOs for sim region code" "1795": "Using transient storage for a SimArena" "2281": "Fixing remaining compiler errors" "2312": "Addressing TODO for clearing hash table" "2553": "Starting to debug the code" "2837": "Altering GetHashFromStorageIndex code to make inspection easier during debugging" "2898": "Continuing stepping through code" "3129": "Found a bug - forgot to update entity pointer" "3165": "Continuing stepping through code" "3294": "Assertion fired on null pointer in RecanonicalizeCoord" "3320": "Stepping through EndSim to figure out assertion" "3515": "Assertion caused by float precision problem?" "3602": "Adding epsilon to IsCanonical to prevent assertion" "3695": "Debugging camera positioning" "3860": "Adding TODOs since we have to stop for today" "3981": "Q&A" "4033": "Assuming we don't go wandering too much on our own, which week has accumulated enough code base for a basic, simple, fully functional game?" "4144": "Regarding high and low entities, would the following solution work? Using one entity struct, all entities are stored in one array, and frequently update the entity if the entity is within camera bounds, and use low-frequency updating if it's outside the camera bounds?" "4305": "Can you give a high-level overview of how entities work now? I get it in bits and pieces, but this week has lost me." "4799": "I'm not sure I fully caught how short-lived/temporary/transient memory is? Is it only for single frames or longer lived? If for longer-lived memory, how do you make sure you don't wrap around and start overwriting memory still in use? Think some homing attack which takes many many frames to resolve." "4885": "How do you determine how much time each sim region should be updated if they aren't updated each frame?" "4914": "How does the work during this experimental phase fit into the final code? Will we be re-using most of it or will we be starting from scratch?" --- name: "day066" title: "Adding Support for Non-spatial Entities" markers: "126": "Where we left off with simulation regions" "172": "Overview of limitation of simulation region - entities currently must have position" "280": "Adding sim_entity_flags" "515": "Updating code for moving collides member variable into a flag" "849": "Making the sword non-spatial" "1011": "Handling non-spatial entities in MoveEntity" "1139": "Handling non-spatial entities in BeginSim" "1199": "Handling non-spatial entities in EndSim" "1269": "Handling non-spatial entities in AddEntity/LoadEntityReference/GetSimSpaceP" "1521": "Handling non-spatial entity in UpdateSword" "1742": "Improving ChangeEntityLocation" "2105": "Debugging GetWorldChunk assertion - problems with storing invalid positions and non-spatial flag" "2371": "Fixing camera following logic" "2454": "Fixing dZ of player" "2583": "Fixing initial camera position" "2673": "Restoring sword functionality" "2799": "Why is the sword's shadow so dark? - Multiple swords" "3021": "Guarding against having multiple entities in sim_region with same storage index" "3443": "Preventing sword being reset when holding down key" "3522": "Q&A" "3606": "Does the current collision code support walls that are not 90 degrees? Say if the wall is at 45 degrees, would the collision code still work?" "3808": "Why not set a boolean value 'to be removed'? It seems like setting the position to an arbitrary position isn't as explicit as setting a flag to say that the entity should be removed on the next update frame." "3903": "The rearranging of code did [introduce] some errors into the code. Is this normal for daily coding?" "4097": "Do we expect most entities to be colliding? If so, does it make sense to have the flag be 'non-colliding' instead?" "4143": "Then why set null position?" "4172": "Would using a tagged union for entity references fix issues we're having with LoadEntityReference?" "4201": "Do you have the whole big picture game architecture in your head at every point, or do you have to check what you did from time to time?" --- name: "day067" title: "Making Updates Conditional" markers: "90": "Reviewing the 'apron' idea for update regions" "664": "Adding Updatable bool to sim_entity" "758": "Setting Updatable bool in AddEntity" "921": "Checking Updatable bool in simulation update" "986": "Setting different bounds for sim_region (UpdatableBounds and Bounds)" "1308": "Does the sword still work? - No" "1385": "Bug - Not setting positions properly when loading entities from references" "1613": "Fixing updating of Familiar" "1706": "Removing non-spatial flag check for sword" "1796": "How to update MoveEntity for more advanced collision effects?" "2024": "Review of iterative movement" "2112": "How to have collision responses within iterative movement?" "2146": "Discussion of callbacks for handling collisions" "2523": "Alternative #1 to callbacks - how to break up MoveEntity" "2637": "Alternative #2 to callbacks - set acceleration and delay calling MoveEntity" "2783": "Implementing alternative #2" "3072": "Bug fixing - MoveEntity shouldn't be called for non-moving or non-spatial entities" "3207": "The sword shouldn't be moving forever..." "3334": "Q&A" "3402": "How will collision be done with moving backgrounds? Such as mazes and moving tiles? Or that won't be in this game?" "3576": "Why don't we use .c instead of .cpp?" "3603": "When you started with enums, why did you start with (1 << 1) instead of (1 << 0?)" "3626": "How big are the source files getting? Are you feeling overwhelmed by the size yet?" "3715": "What happens when you somehow glitch through a wall? Will the game crash?" "3767": "How many lines have you written so far?" "3792": "In what situation would you prefer callbacks to a huge switch-case block?" "4060": "Do we load and draw everything manually to a DIB section, then blit the final image?" "4095": "After you mentioned the 'do all collisions at one time' thing, it seems like in addition to being greatly easier to implement, it also matches the real-world better, like summing all the forces to get the net direction. Why would anyone every want to do an update function for each object?" "4182": "I [Jonathan Blow] use cloc to count lines. It is pretty decent." "4326": "Besides the bits that are obviously tacked on, would you consider the Windows GUI a good API?" "4420": "I guess I should have asked how big it has to get for you to start feeling overwhelmed." "4469": "How'd you decide on this order to build up the engine? Was it intuition or experience?" "4749": "Speaking of UML and diagrams, do you ever use class schematics for code planning?" "4782": "Don't you need to be able to enumerate every possibility in order to use a switch statement? What if you wanted to make a system that can be extended?" "4893": "Why use switch statements instead of just big if-else blocks?" "4914": "Will the way in which collisions are handled be order-independent?" "4976": "Is it better to debug as you go or towards the end of a programming cycle?" "5105": "Actually you want to pass --no3, otherwise it [cloc] is lying about the number of lines - it is dumb." "5199": "Will the game have multiplayer and/or co-op?" --- name: "day068" title: "Exact Enforcement of Maximum Movement Distances" markers: "28": "Recap of where we are with collisions and interactions" "67": "Bug fix from forums - Typo in MoveEntity for testing entity flag" "224": "Overview for today - max movement distances" "477": "Review of MoveEntity" "562": "Review of tMin usage in MoveEntity" "816": "Starting implementation with a maximum distance" "968": "Discussion about cost of square roots" "1041": "Using a ratio to cap tMin" "1309": "Updating DistanceRemaining" "1361": "TODO for Epsilon for (PlayerDeltaLength > 0) ?" "1417": "Adding DistanceLimit to sim_entity" "1597": "Decrementing DistanceLimit" "1687": "Testing out the changes" "1735": "Discussing collision response and double dispatch" "2575": "Alternative to entity type double dispatch - fundamental quality double dispatch" "2846": "Starting to add entity type double dispatch first for collision handling" "3270": "Why sword-monstar collision won't work quite yet - need to respond to collisions but not stop movement" "3506": "Q&A" "3580": "How long in your opinion does it take to become fluent on Emacs?" "3610": "Could an entity have multiple fundamental quality property things?" "3731": "When are you planning to add depth sorting?" "3753": "Will there be enough entities that some optimization will have to happen? How many do you expect to have on a screen? Hundreds?" "3869": "I'm not sure I quite follow your argument for double-dispatch table versus fundamental qualities. Seems to me like you still need to figure out what to do for each quality, what to do in the presence of others, still leads to quadratic growth." "4254": "Yesterday you were talking about using callbacks for the collision system. Will this new system replace the need for them?" "4290": "Casey, I asked a question and the Twitch app crashed on iPad. Any chance you my questions before it did?" "4340": "Casey, as a casual observer and occasional troll, where is the game now? Seriously, I haven't watched for a while, and how do you find the energy to do this weeknights?" "4594": "I noticed sometimes you try to determine regions for collision boxes. Why not implement basic shapes and use those as debug helpers with some alpha percentage?" "4696": "Do you test for collision every update interval? If your sword overlaps with an entity, could it happen that a moving entity gets missed because both entity and sword move in the same tick above and beyond each other?" "4827": "To me it seems as the sword should be influenced by the speed of the player movement at the time it was dispatched? Am I right?" "5004": "I missed the part on how many entities you are simulating at once and where you store them, but won't the dispatch table approach be negative for cache performance? Could its simulation be deferred?" "5098": "It seems logical to make infinity the default maximum distance an entity can travel, but that could have performance implications. Could you say something about that?" "5174": "Could you also do something like that for AI, where for instance, you can impose simple behaviors on top of each other randomly, to make complex and varied behavior, instead of doing the more common behavior tree approach?" "5192": "If you do the AAA-ness way, can you come back to it later and edit or add more details to it like from 6-to-8, etc., or will that cause problems?" --- name: "day069" title: "Pairwise Collision Rules" markers: "95": "Recap of where we left off with collision responses" "284": "Changing things so that stopping on collision is part of collision handling" "385": "Overview of ignoring certain collisions" "820": "Restructuring collision code for ignoring certain collisions with rules" "1413": "pairwise_collision_rule and collision rule hash table for ShouldCollide" "1887": "Tricky problem - How to remove collision rules?" "2051": "AddCollisionRule function" "2382": "Adding first rule - sword shouldn't collide with entity that throws us" "2515": "Adding collision rule when StopsOnCollision is false" "2617": "Problem - Don't want to keep on adding new collision rules" "2836": "Clearing collision rules for an entity" "3495": "Debugging collision rule code" "3845": "Q&A" "3903": "What stops us from programming a game that directly boots into BIOS (hooks up to hardware as low as possible basically)?" "4031": "Do you ever use function pointers?" "4147": "Should the thrown entity have the player's direction/speed added to its thrown speed/direction so you cannot catch your own throws?" "4234": "Could you explain again why you should order the entities before processing the properties?" "4350": "Isn't there a potential bug in MoveEntity if an entity happens to spend the whole distance limit, which gets set to (0,0), and then gets considered unlimited in the next frame?" "4447": "Can the pointers in the hash function become a memory problem?" "4601": "I have two gameplay requests - A non-euclidean room and a monster that spans multiple rooms vertically. Are those things possible?" "4751": "Are renderers reusable?" --- name: "day070" title: "Exploration To-do List" markers: "29": "Overview of the development process" "243": "Recap of collision rule hash table" "353": "Problem with removing collision rules from hash table" "484": "Simple solution, with trade-off, for quickly finding collision rules for entity in hash table - but not doing quite yet" "1237": "Bug in AddRadiusTo" "1386": "Brainstorming stuff to do" "1754": "TODO: Animation/Rendering" "1833": "TODO: GAME" "1884": "TODO: Rudimentary world gen" "2005": "TODO: AI" "2072": "TODO: Collision detection?" "2114": "TODO: Implement multiple sim regions per frame" "2185": "TODO: Metagame / save game?" "2471": "TODO: AI - Rudimentary monstar behavior example" "2482": "TODO: Z!" "2586": "Reviewing the TODO lists - What's hard and what's easy?" "2662": "TODO: Audio" "2778": "TODO: Metagame - save slots" "2928": "In-game UI hopefully not needed" "2956": "TODO: Debug code" "3033": "TODO: Rudimentary world gen - Map display" "3094": "Will you be carrying multiple items?" "3128": "Sorting the TODO lists" "3402": "Q&A" "3442": "Isn't doing this list thinking too far ahead or thinking too far according to your compression-oriented programming?" "3555": "In the GetHashFromStorageIndex function, you do some bit-twiddling to map hash value into hash index. Is there a reason that you didn't just compute hash index as hash index = hash value MOD array count?" "3799": "Right now the familiar lags behind since it moves slower than the player. There may be many legitimate situations where the player and familiar may be separated. Have you considered implementing a proportional integral derivative controller for its speed?" "3884": "Could you briefly go over the solution for the collision table again?" "3896": "Do we have to do z-sorting? For a game like this, can't we just sort on the y-axis, and do things to simulate climbing stairs (change the velocity as the character moves up something like stairs and what have you)?" "3988": "I heard you talking about animations and see you wrote down a skeletal system. Do you have plans on importing from a pre-made program or making an animation program for the artist to use?" "4077": "For the list - Superfish!" "4135": "Asset loading management is missing from the list." "4180": "What 2D game can you think of that did good z-movement? I personally always liked Prince of Persia when he climbed the steps at the end of the level." "4232": "Have you seen watchpeoplecode.com?" "4280": "What is your opinion on using existing code someone else wrote as a learning tool?" "4378": "Spriter's file format is completely open and documented." "4404": "Do you want to have quests in the game? In this case, how are you planning to define them?" "4448": "I think we dropped the check for Entity == HitEntity in collision code last time, or did I miss something?" "4503": "Will you patent the monstar pathfinding algorithm?" "4562": "For z-axis movement, would it be feasible to resize the sprite to be larger as they move up, and then resize the sprite to be smaller once it reaches the level, while doing some parallax stuff on the wall textures for the second resize?" "4678": "I think Pokemon 3rd gen/1st gen did good stuff with the z-axis." "4715": "Will the monstar encounters be random based (like Final Fantasy, Dragon Warrior) or will they be more static (Zelda style)?" "4750": "Should there be a time limit as well as a distance limit on the sword?" "4809": "Minish Cap handles the z-axis really well." "4816": "How exactly does your question sorting plugin work?" "4833": "I believe Ultima Online did some stuff with z-axis, but I'm not sure if it's good though." "4873": "What's the biggest game project you personally worked on?" "4934": "No remark on handmade animations? Or did I miss that?" "5001": "I've been writing my own platform layer in my own code, and I've found I've been 'poisoned' by your approach. By this, I've been heading down by a path very similar to yours simply through knowledge of a possible solution to it. This leads me to a very narrow way of thinking about problems. Do you run into this as well? How do you break through the wall? It takes me a very long to get solutions that fit my needs when I see someone else's." "5318": "How long do you think a good game should be?" --- name: "day071" title: "Converting to Full 3D Positioning" markers: "15": "Recap" "67": "Casey talk about "The coincidence of how people use their TODO notebook"" "172": "Bug fix: Remove the code we left when we were playing around with familiars" "339": "Decide what to do today: Clean up things by using v3" "361": "Get rid of the struct "world_difference" and fix other places we were using it" "496": "handmade_world.h: Change ChunkSideInMeters to v3" "585": "handmade_math.h: Implement the Hadamard product" "676": "handmade_math.h: Clone v2 operations for v3" "914": "handmade_world.h: Offset_ is v3 now" "960": "Point out the puzzler from world_position can be solved because we now no longer operate on entities without bringing them into the sim_region" "1048": "Back to deal with compiler errors" "1417": "The ground plane should not be the negative bottom sides of Tiles because we want to prevent things from accelerating near the Z bound" "1572": "handmade_world.h: Tidy up the function ChunkPositionFromTilePostion" "1754": "handmade_math.h: Use anonymous struct in union to grab part of the elements we are interested in v3" "1914": "handmade_math.h: Make a v3 "constructor" that append a v2 with a real32 value" "1985": "handmade_sim_region.h: Upgrade P/dP in sim_entity to v3" "2027": "Keep on dealing with compile errors" "2137": "handmade_math.h: rectangle3" "2194": "handmade_math.h: AddRadiusTo should take a vector as a parameter" "2274": "handmade_sim_region.h: Upgrade MoveEntity routine to v3" "2600": "Get rid of GetCameraSpaceP" "2615": "Keep on cleaning up" "2840": "Program now can be compiled" "2857": "Run the game and find out there is absolutely nothing except our hero" "2881": "Make sure that rectangle bound set up properly" "2913": "Blackboard: Explain what we want to make sure in more detail" "3417": "The bug might be Casey broke something in terms of how to store things into chunk position" "3493": "Q&A" "3531": "Have you considered using macros that take a name and operator to paste in simple vector functions?" "3602": "What kind of almond milk are you drinking?" "3612": "Do you have any suggestions on how to keep up with your 5 episodes a week, when me and my friend have only started watching your videos from the beginning last week?" "3682": "Why type 1.0f instead of 1.0?" "3748": "Have you considered writing tests?" "3936": "Can you explain what your Z really means? If it's for separating levels, should tall walls be able to poke into the upper Z layer(s)?" "3996": "Reminder: Monster that you fight on two floors at once, going up and down stairs to fight the bottom or the top" "4054": "How do you tab between things so quickly?" "4119": "How good of a computer do I need to smoothly code?" "4219": "I love you... Will you marry me?" "4236": "How smooth is it transitioning a knowledge of Python into C++" "4286": "Have you thought more on how the Z-axis will look when finally implemented?" "4355": "When you work on a game do you work on one project or do they contract you for multiple projects?" "4370": "Do you think about data locality all the time, to reduce cache misses?" "4477": "How long have you been programming?" "4490": "Are you done working for real - made all your money, and this is just for fun / philanthropic reasons?" "4510": "How do you determine what gathers in a chunk with the Z-axis? Do you grab entities from all 6 sides of the chunk?" "4527": "Blackboard: "Axis aligned bounding box"" "4691": "handmade.h: TODO(casey): Minkowski inclusion test for sim region begin / updateable bounds" "4768": "I recently watched Jon Blow's talk on attempting deep work and became curious: Do you do anything similar from a psychological perspective, i.e. go dancing like Jon does or do you have some other relaxing / rewarding activity that helps to spawn creative thought or gain elusive insights into problems you are struggling to solve?" "4868": "Do you think RK4 integration is "overkill" for a 2D game like Handmade Hero?" "5065": "Hi, just tuned in so it might have been mentioned before, but why are you using assertions in non-test code?" "5378": "What about having two regions - one outer and one inner, include entities that move into the inner and exclude entities that move out of the outer - so there's a "margin" that allows some moving without ping-ponging right across a hard in / out line?" "5473": "Call it" --- name: "day072" title: "Proper 3D Inclusion Tests" markers: "48": "Coding from scratch, "just like mommy used to code"" "57": "Recap" "111": "Fix IsInRectangle cut/paste bug" "184": "Fix ChunkPositionFromTilePosition bug" "288": "Debug MapIntoChunkSpace precision problem" "431": ""Just do the code and let it go..."" "547": "Debug jumping over the world problem" "822": "Diagramming jump into the next highest chunk" "995": "Found the problem!" "1181": "Solving the world_position puzzler" "1287": "handmade.h: Comment out world_position P;" "1716": "Actually, the world_position puzzler is unsolvable" "1884": "Next up: Minkowski inclusion test" "1905": "Frinstances" "2010": "Diagramming the problem" "2176": "Related problem: finding colliding entities outside the test area" "2532": "Implementation of the simpler option" "3461": "Q&A" "3581": "We had a bit of a troll problem today. Hang on" "3623": "Pasta was gross" "3637": "What was your grade on APCS?" "3704": "I just joined the stream, so sorry if this has been answered, but what math classes did you take in high school, and what grades did you get?" "3732": "I noticed a bunch of your functions are inlined. Is there a difference between using regular functions and inlined functions?" "3944": "Day 72, how much longer do you think it's going to take?" "4010": "Could you take a look at players collision? They spawn very close to each other" "4042": "Since there's not much in the way of questions, where do you get your Almond Milk from?" "4062": "This is my first time watching your stream, and I would like to learn how to code. This seems like a cool stream to watch, but I don't know your streaming schedule. So basically, what's your streaming schedule?" "4090": "Are there are any good use cases for 4D vectors?" "4112": "Blackboard: 4D Vectors" "4261": "General programming question: Do you tend to order your functions in any sort of order - public / private / static - or even flow-wise - Function A calls Function B? Do you tend to always put one above the other, or do you never think about it?" "4323": "Will you extend your Minkowski collision implementation to deal with rotation / arbitrary convex polygons in the future?" "4514": "Why is Win32 Mouse Handling so annoying - WM_LMOUSEDOWN but no WM_LMOUSEUP if you leave your window, WM_MOUSELEAVE unless you get alt-tabbed away, SetCapture helping if you leave the window, unless alt-tab..." "4567": "Casey, when will the Z-index of the entities occur?" "4581": "Is anyone here old enough to miss the great space coaster?" "4604": "Do you ever foresee the project getting to a stage in which you accept pull and merge requests from other developers to fix bugs, add features or other things? Of course you would first have to start using version control before your hard drive fails" "4649": "I've jumped from, like, episode 12 in the archive to the stream, so forgive me if this has been answered before, but why does the player even need to jump?" "4690": "Create a second player by using the Xbox controller, it will be very close to the one created by a keyboard, so both cannot move" "4778": "What's the most elegant / sexy piece of code in the game so far?" "4902": "What program do you use for your blackboard?" "4917": "If I am not mistaken, in your code you didn't need to use any forward declarations and come up against cyclic dependencies up until now. Is this by chance or did you try in your head not to have them when writing up new functions / structs?" "5019": "Entities drawing back to front" "5039": "Will there be a Handmade Hero Convention annually, after game release?" "5065": "Are you implementing any advanced data structures and would you recommend learning assembly to aid in optimizing C programs? Any tips on practice?" "5169": "Is there such a thing as a 'hardware' cursor as compared to a 'software' mouse cursor?" "5300": "We are out of time" --- name: "day073" title: "Temporarily Overlapping Entities" markers: "57": ""Little tiny baby zipfiles"" "126": "Recap and plan for the day" "249": "handmade.cpp: Load rock02.bmp into the set" "301": "handmade_sim_region.h: Add EntityType_Stairwell to entity_type" "402": "handmade.cpp: Re-enable DoorUp and DoorDown" "464": "Talk about adding an entity for the stairwell" "527": "Introduce AddStair" "803": "Run the game and see our new stairwell" "830": "Consider how to implement the stairwell" "923": "Blackboard: Traversing stairs" "1102": "Blackboard: Inside / Outside" "1311": "handmade_sim_region.cpp: Introduce the concept of the player being within regions of space" "1585": "Blackboard: Specifying the traversable area of the stairwell" "1654": "handmade_sim_region.cpp: Continue writing the inclusion check" "2523": "Blackboard: Checking to see if two rectangles intersect" "2802": "handmade_sim_region.cpp: Write RectanglesIntersect" "2995": "HandleCollision between the Hero and a Stairwell" "3093": "Try passing through the stairwell" "3113": "Debugger: Step into HandleCollision" "3226": "handmade.cpp: Make AddCollisionRule return a boolean which states whether or not the entity was already added" "3346": "handmade_sim_region.cpp: Record the fact that you've added a collision rule if it's new" "3447": "handmade.cpp: Intrdouce RemoveCollisionRule" "3547": "handmade.h: Introduce pairwise_collision_rule_flag" "3629": "TODO(casey): Transient collision rules! Clear based on flag" "3784": "Q&A" "3883": "Q: Why did you decide to code at, like, 4?" "3920": "Q: Glad to see the A-A B-B collision detection code come up. Took me way too long to figure that one out" "4190": "Q: You mentioned yesterday about choosing between two ways to solve the problem of large entities that overlap the sim region but are not in the selected chunks. It looked to me like you could use both solutions. If the entity is larger than the max entity size, still allow it and use the add it twice approach. Would this get you all the advantages of both with neither of the disadvantages?" "4296": "Q: Would it make sense to just put a wall of 1/3rd the length on each side of the stairwell to handle the collision?" "4335": "Q: Is the TODO list in the platform layer a more or less comprehensive list of changes you would do before shipping, or are there some additional things one should note?" "4362": "Q: Yesterday you mentioned that when jumping up to a chunk above, the character would jump over the ground level Z=0 and then come down, however, since the jump code is making the Z position go to 0 from negative, wouldn't the character be pushed up to 0 as soon as it reached the low side of the upper chunk, and won't this cause problems when trying to move the character up the stairs?" "4437": "Q: All of the these algorithms all specify convex shapes. Is there anything usable for concave shapes, or is it usually always the case that it's better to just split up a concave shape into multiple convex shapes?" "4511": "Q: About the TODO list, you mentioned a while back that you want to code some sort of zooming out that would let you see entities outside the sim region" "4530": "Q: An episode on metaprogramming, please?" "4578": "We're out of time" --- name: "day074" title: "Moving Entities Up and Down Stairwells" markers: "91": "Blackboard: Processing entities in pairs" "263": "Blackboard: Using that table to process stairwell overlapping" "417": "Blackboard: Travelling inside the stairwell" "547": "Blackboard: Letting the stairwell take control" "638": "Blackboard: Lava" "838": "handmade_sim_region.cpp: Remove the WasOverlapping check" "912": "Add HandleOverlap to MoveEntity" "1079": "Compile and double check that it's still working" "1093": "Write CanOverlap and HandleOverlap" "1259": "Consider reconceptualising the Ground" "1452": "Continue writing HandleOverlap" "1523": "Learn something new about the codebase" "1529": "handmade.cpp: Draw the Stairwell as a rectangle" "1608": "Take a look at the stairwell and describe what we want to do" "1648": "Blackboard: Handling both ends of the stairwell" "1728": "Blackboard: The concept of mapping for any rectangle" "2079": ""This means nothing"" "2117": "handmade_math.h: Introduce GetBarycentric" "2202": "Introduce SafeRatio functions" "2343": "Use GetBarycentric in HandleOverlap" "2472": "Blackboard: Lerp" "2561": "handmade_math.h: Introduce Lerp" "2585": "handmade_sim_region.cpp: Use Lerp in HandleOverlap" "2636": "Handle the stairwell collision in CanCollide" "2661": "Run the game and try walking through the stairwell" "2690": "Debugger: Step into HandleOverlap" "2738": "handmade_sim_region.cpp: Check for things overlapping themselves" "2775": "handmade.cpp and handmade_sim_region.h: Introduce EntityFlag_Moveable" "2893": "handmade_entity.h: Pluralise the Flag functions" "2946": "Debugger: Step into HandleOverlap" "2985": "We already need the clamp" "3005": "Blackboard: How a guy can overlap the stairwell despite his point not being in it" "3036": "handmade_math.h: Introduce Clamp functions" "3171": "Debugger: Step into HandleOverlap and ensure that our barycentric coordinates are normalised" "3228": "Blackboard: Positioning our stairwell" "3302": "handmade.cpp: Do an offset of that ChunkPositionFromTilePosition, because he can" "3356": "handmade_world.h: Make ChunkPositionFromTilePosition take AdditionalOffset" "3387": "Run the game and look for the stairwell" "3412": "handmade_sim_region.cpp: Gather entities by ChunkZ correctly" "3494": "Run the game and see two levels at the same time" "3539": "Debugger: Step into HandleOverlap and find that we're not hitting the test" "3623": "Debugger: Investigate why the inclusion test fails" "3695": "Blackboard: The perils of not having the concept of Ground" "3792": "handmade.cpp: Make the stairwells bigger for now" "3838": "Run the game and find we're lerping properly" "3878": "handmade_sim_region.cpp: Use our Ground value" "3897": "Run the game and find that we're getting closer" "4000": "handmade_sim_region.cpp: Additionally test the entities' Z planes to determine if they CanCollide" "4027": "Run the game and find that we're sort of getting there" "4120": "Q&A" "4151": "Is the familiar going to be programmed to be able to go through the stairwell or instantly teleported to the floor?" "4204": "When are we going to do priority for which sprite is in front and in the background? (I don't know what that is called)" "4322": "You mentioned that you'll be able to attack from below / above. Will you be able to do that on the stairwell?" "4379": "I've just started to see your videos, but you already talked / programmed about entity systems. Will you use it here?" "4440": "Does the scope of this application include moving environments, so you will need to introduce logic to detect movement of assets?" "4490": "Will the game have color grading for different areas, e.g. the blue & black cloak the hero wears might appear as two other colors in some lighting conditions?" "4560": "What are the piece groups and how are they used / useful for our current use in sprite rendering?" "4635": "Can you please, forgive my French, somehow un *** the net coding for DayZ Standalone and finish what Dean "Rocket" Hall gave up on?" "4697": "Will enemies follow you upstairs or down? If they do, how will the space outside the camera work?" "4724": "How will you handle sprite animation? Are you using a library and have you ever hear of the Spine 2D skeleton animation framework?" "4791": "Who is that guy?" "4897": "I mean with there being different floors will it be different? I am assuming not" "4968": "Can you run this game so some of us see its current state?" "5214": "Okay, so you know how we have the camera space and then there's a space outside that we can't see but entities are still moving? Will we need to edit that code to make it work on "Vertical" floors? It's okay if you don't get it. I may be thinking too far in" "5282": "Would we use a fixed, discrete animation for moving up and down stairs a la Link to the Past, or would the goal be to make movement seamless?" "5344": "How much lines of code do you have at the moment?" "5395": "That is the end" --- name: "day075" title: "Conditional Movement Based on Step Heights" markers: "238": "Blackboard: Handling stairwell traversal" "465": "Blackboard: Collision Detection in Z" "501": "Blackboard: Draw reasonably" "515": "Run the game to show the multiple visible floors" "667": "handmade_sim_region.cpp: Prevent the entities from being accelerated by gravity while on the ground" "741": "handmade_sim_region.h: Introduce EntityFlag_ZSupported" "780": "handmade_sim_region.cpp: Use EntityFlag_ZSupported" "890": "handmade.cpp: Take out the stairwell height padding" "944": "handmade_sim_region.cpp: Add a BreakHere variable in MoveEntity" "965": "Debugger: Step into this point in MoveEntity" "1054": "Debugger: Note that EntityFlag_ZSupported is only being set when we're under the Ground" "1074": "handmade_sim_region.cpp: Change that if statement to include the Ground" "1099": "Debugger: Step into that point in MoveEntity" "1231": "handmade.cpp: Give the stairwell some Z depth" "1291": "Run the game and jump through the layers and find that we do now collide with the stairwell" "1348": "handmade_sim_region.cpp: Specify another criteria to determine when we want to stay pegged to the ground" "1445": "handmade.cpp: Stop the Familiar from following us" "1457": "Walk up and down the stairs" "1539": "handmade.cpp: Make the stairwell a little longer" "1683": "Run the game and demonstrate teleporting to the top of the stairs" "1712": "Blackboard: Consider building the stairwells out of multiple things" "1805": "handmade_sim_region.cpp: Consider doing a speculative collide test on the stairs" "1953": "handmade_sim_region.cpp: Introduce TestWallNormal, TestHitEntity and SpeculativeCollide to do these speculative tests" "2398": "Debugger: Step into SpeculativeCollide and find that we are not hitting the stairwell" "2472": "handmade_sim_region.cpp: Flip the logic of SpeculativeCollide" "2486": "Run the game and find that the stairwell is behaving as expected expect for the fact that we're not gliding along it, and also that we are now not colliding with walls" "2554": "handmade_sim_region.cpp: Tweak the logic of SpeculativeCollide" "2606": "handmade_sim_region.cpp: Stop setting StopsOnCollision = false" "2622": "Run up and down the stairs and note how good it feels" "2728": "handmade.h: Attend to the TODO list" "2813": "handmade_sim_region.cpp: Add DefaultGroundLevel to sim_region" "2876": "handmade_sim_region.cpp: Compute the DefaultGroundLevel based on the information in BeginSim" "2912": "Blackboard: Specifying the ground levels in a given sim region" "3029": "handmade_sim_region.cpp: Rename DefaultGroundLevel to GroundZBase" "3086": "Blackboard: Snapping to the correct ground level" "3227": "handmade.h: TODO(casey) Need to make a solid concept of ground levels so the camera can be freely placed in Z and have multiple ground levels in one sim region" "3273": "Run the game and note that the Familiar and Monstar are erroneously getting snapped up to our Z level" "3319": "handmade.cpp: Tweak entities' positions based on their Z level" "3513": "Q&A" "3558": "I'm guessing the engine will manage arbitrarily high ground levels? Would you really want that? Gameplay such as projecting attacks to a monstar below does sound fun" "3648": "Why not use the X and Y positions as they appear on the screen for detecting sim regions?" "3678": "Should you also check the "stair step" at the top of the top of the stairs? It seems you can exit earlier than at the bottom" "3781": "Could you please do an overview, on blackboard maybe, of the "entities position system" (world, screen, etc.) now that it's "done"? I'm having trouble understanding it (hopefully you'll understand my question)" "3999": "Why is the order of stuff drawn on the screen janky (some trees overlap others, some are proper)?" "4006": "Isn't it easy to draw them in order - each layer draws entities left to right, top to bottom?" "4089": "Is the reason why things in different levels seem shifted up due to the Z-offset when rendering?" "4155": "Will this cause for the wall on the top to be drawn above the screen when the camera is locked instead of following the character?" "4192": "When you are allocating everything with custom memory allocators, do you only use the stack for pointers?" "4225": "Are you not worried that three dimensions might complicate entity A.I. to the point where it impacts performance?" "4281": "Casey, can you check your forum registration process? I never got a confirmation email - registered a couple of days ago" "4343": "When will you switch back to centered camera? It seems to be missing on the TODO list" "4364": "Any particular reason behind making the chunk origin the center of the chunk rather than one of the corners?" "4427": "Sorry for being unclear. Do you store anything else than pointers on the stack?" "4474": "If the camera were far away enough from the player, would the player go into a simpler routine like the rest of the entities?" "4496": "Should the possible collision test use the TestHitEntity instead of the TestEntity or are they the same? Can you briefly go over the flow of the HitEntity changes?" "4890": "You could now cancel out the first HitThis == true and not do other checks" "4986": "We have agreed to go on break for a week" --- name: "day076" title: "Entity Heights and Collision Detection" markers: "154": "Start everything up, make sure it's all still working and plan for the day" "381": "handmade_sim_region.cpp: Consider confining collision detection to the entities' Z neighbourhood" "581": "Blackboard: Extending Minkowsi collision into the third dimension" "709": "handmade_sim_region.cpp: Check Rel.Z against the MinCorner and MaxCorner" "778": "Run the game and find that we're passing through everything" "797": "Debugger: Step in and inspect the MinCorner and MaxCorner" "899": "handmade.cpp: Give the wall and other entities some height" "1018": "Run the game and find that we now stop correctly" "1080": "win32_handmade.cpp: Ensure that we're not passing WS_EX_LAYERED to CreateWindowExA" "1185": "Blackboard: Conceptualising TileSideInMeters" "1449": "Blackboard: Conceptualising WorldChunk" "1707": "handmade_world.cpp: Pass in TileDepthInMeters to InitializeWorld" "1776": "Blackboard: Competing Gathers" "1949": "handmade_world.cpp: Update ChunkPositionFromTilePosition to reflect our new Tile dimensions" "2097": "Postpone this until we have debug visualisations" "2143": "Run the game and double check that it's working properly" "2178": "handmade.cpp: Specify the height of things" "2265": "handmade_math.h: See what RectanglesIntersect does" "2330": "Blackboard: Inclusion tests" "2524": "Blackboard: Checking overlaps" "2628": "handmade_math.h: Change the tests in RectanglesIntersect" "2695": "Run the game and find that we are unexpectedly still working properly" "2735": "Investigate what's happening with the stairs" "2819": "Blackboard: Understanding entity placement" "2935": "handmade_sim_region.cpp: Take a look at where Dim is being used" "2999": "handmade.cpp: Introduce AddGroundedEntity" "3180": "Pass AddGroundedEntity to AddWall" "3248": "Run the game and double check that it worked" "3277": "handmade.cpp: Pass AddGroundedEntity to AddStair, AddPlayer, AddMonstar and AddFamiliar" "3486": "Run the game and see where we're at" "3520": "Debugger: Step into AddGroundedEntity" "3567": "handmade.cpp: Consider fixing the drawing code" "3716": "Q&A" "3782": "Q: That kid you just created is around two foot tall" "3810": "Q: Better data is at halls.md" "3843": "Q: I was wondering, why do you have two windows open and not just one?" "3893": "Q: Over four feet seems right for a seven year old" "3942": "handmade.cpp: Make the Hero 1.2 metres tall" "3992": "Q: What apps are you using for the dev environment?" "4075": "Q: Any recommendations for tracking down heap corruption bugs?" "4568": "Q: If you're not allocating memory as the game goes, are you allocating a bunch at the start? How does that work?" "4633": "Q: What are the Linux equivalents to these functions?" "4673": "Q: How far along are we in developing the game?" "4788": "Q: munmap is another Linux equivalent call" "4802": "Q: Is this in C++?" "4871": "Q: Does C++ compiler generate hidden code like constructors, copy constructors, etc., in the way that you structuring the game?" "4974": "Q: Do you use the STL at all in your code?" "5058": "Call it" --- name: "day077" title: "Entity Ground Points" markers: "120": "Recap the bug from yesterday" "242": "Blackboard: The discrepancy between the Entities' base points and the Ground position" "330": "Look at how these concepts are currently specified" "426": "handmade_sim_region.cpp: Add 0.5*Entity->Dim.Z to Ground" "451": "Run the game and find that we're not quite right" "526": "Debugger: Step into the code where Ground is calculated" "605": "handmade.cpp: Look at the current drawing code" "914": "Introduce EntityBaseP" "1031": "Run the game and find that we seem to have solved the problem" "1091": "handmade.cpp: Add two rectangles to the Stairwell" "1200": "Work on the ZFudge" "1350": "Check out the effects on the Familiar" "1386": "MetersToPixels is getting pre-multiplied by OffsetZ" "1457": "Run the game and see it looking more correct" "1514": "handmade.cpp: Don't bother adding OffsetZ" "1554": "Blackboard: What the ZFudge is doing" "1691": "handmade_sim_region.cpp: Look at SpeculativeCollide" "1733": "Introduce GetEntityGroundPoint" "1818": "Use GetEntityGroundPoint to set EntityBaseP and Ground" "1889": "Blackboard: Computing the Ground displacement" "1961": "Run the game and find we can now go upstairs" "1989": "handmade.cpp: Make stairways extend above the ground" "2076": "Blackboard: Understanding StepHeight" "2218": "handmade_sim_region.h: Add WalkableHeight to sim_entity" "2281": "handmade.cpp: Use that WalkableHeight in SpeculativeCollide" "2317": "Run the game and try the stairs" "2359": "handmade_entity.h: Introduce GetStairGround" "2641": "handmade_sim_region.cpp: Convert HandleOverlap and SpeculativeCollide to use GetStairGround" "2815": "Run the game and find that that fixed our problem" "2848": "handmade_sim_region.cpp: SpeculativeCollide needs to know whether we're coming on to or moving off a stairwell" "3041": "Q&A" "3135": "Q: Do you use Clang on Linux?" "3168": "Q: What is the best way to learn C++ from absolute scratch on my own?" "3236": "Q: Do you know anything about Voxpel programming?" "3275": "Q: What versioning and revision control system do you use?" "3283": "Q: Are you planning on replacing the stairs in your house with ramps?" "3376": "Q: How did you get the right side of your Visual Studio debug view to be split vertically?" "3469": "Q: Why do you use so many magic numbers in your code?" "3488": "Q: What do you think about friend classes?" "3510": "Q: Is this turning into reverse Doom? Almost complete 3D rendered in 2D, instead of 2D rendered in 3D" "3630": "Q: Is the top layer going to fade in if you go up the stairs into a closed room?" "3661": "Q: When do you plan on doing Z-sorting with the sprites?" "3676": "Q: Why do you use so many magic numbers in your code? Why so many #defines?" "3733": "Q: Are you planning to use advanced shader techniques? If so, which ones?" "3760": "Q: Looks like I skipped an episode in which you made a lower level visible from a higher one. Do you remember when did it happen? Is the floor going to remain transparent in the future?" "3823": "Q: My previous question was on topic. Missed it, maybe" "3841": "Q: Correct me if I'm wrong, but it seems early on we started with a bottom-centre position for collision detection on our hero. We moved to a centre position which was offset in both X and Y. Now it seems we use a centre X and Y and are continuing to compute the bottom-centre position. Do you feel this needs to be consolidated in any way?" "3950": "Q: What's with the floating head in the middle of the forest?" "3974": "Q: Could you explain the line ControlledHeroes[ArrayCount(((game_input *)0)->Controllers)]; in handmade.h because it looks like you're casting a null pointer and referencing" "4130": "Q: To workaround the Mischief zoom issue, how about you find the zoom level you want then draw four dots, one in each corner, then when you come back you can align those dots back to the corners" "4150": "You could use C++'s decltype or typeof to find that ArrayCount" "4271": "Could you do it: ArrayCount(game_input::Controllers)?" "4300": "Q: declval is what you want" "4404": "Q: Why do you plan on using OpenGL or DirectX for hardware acceleration? Is that something that you have to have knowledge of actual GPU architecture to be able to implement?" "4487": "Q: What do you think of Khronos Vulkan?" "4578": "Q: What is the best way to build a game when you know how to program but you have no art skills? Hire an artist to do it for you? That is my Achilles' heel, but I want to make a game on my own" "4698": "We have come to the end" --- name: "day078" title: "Multiple Collision Volumes Per Entity" markers: "97": "Blackboard: Position != Collision "Mesh"" "553": "handmade_sim_region.h: Introduce sim_entity_collision_volume" "654": "Blackboard: Two ways of storing this collision volume data" "771": "handmade_sim_region.h: Introduce sim_entity_collision_volume_group" "909": "Compile and be guided by the compile errors in replacing the Dim" "943": "handmade_sim_region.h: Add WalkableDim to sim_entity" "1058": "handmade_entity.h: Use WalkableDim in GetStairGround" "1171": "handmade_math.h: Introduce GetBarycentric for rectangle2" "1218": "handmade_math.h: Introduce Clamp01 for v2" "1263": "handmade_sim_region.h: Add sim_entity_collision_volume TotalVolume to sim_entity_collision_volume_group" "1391": "handmade_sim_region.cpp: Pass sim_entity_collision_volume to EntityOverlapsRectangle" "1551": "handmade_sim_region.h: Specify that the VolumeCount is always expected to be greater than 0 if the entity has any volume" "1641": "handmade_sim_region.cpp: Iterate over the Volumes" "1684": "Blackboard: Collision detection is an o(n^2) problem" "1802": "handmade_sim_region.cpp: Continue writing this loop" "2038": ""Don't ask me why I'm doing this renaming"" "2131": "Casey is out of tea" "2141": "Dream of gourmet tea" "2233": "handmade.h: Add sim_entity_collision_volume_groups to game_state" "2757": "handmade.cpp: Use the WalkableDim to draw the Stairwell" "2816": "handmade.cpp: Implement MakeSimpleGroundedCollision" "3070": "handmade.cpp: Do InitializeWorld earlier" "3095": "Run the game and find that we're not totally busteD" "3147": "handmade.h: Flying things can now go over low walls" "3187": "handmade.cpp: Initialise the WalkableDim in AddStair" "3278": "handmade_math.h: Introduce ToRectangleXY" "3353": "Run the game and see that our stairwell is back" "3378": "handmade_sim_region.cpp: Reenable the stairwell collision" "3443": "Run the game and try jumping over the stairwell" "3504": "handmade.cpp: Implement MakeNullCollision" "3590": "Run the game and note the weird effect of gravity while falling down the stairwell" "3664": "handmade_sim_region.cpp: Set Drag.Z = 0.0f" "3709": "Run the game and fall down the stairwell" "3728": "Q&A" "3758": "Run and jump around" "3816": "Can we get a sneak preview of the fundamental types arena?" "3823": "Blackboard: Fundamental Types Arena" "3903": "Besides the missed keys" "3968": "What did I just watch?" "4130": "Could you sketch what you did today visually? Was it just changing the collision paradigm?" "4135": "Would the ground collision be easier / have less issues if it was a volume instead of a plane?" "4187": "Blackboard: Specifying the ground" "4368": "Since you are handling Z, how complicated is it to have entity stacking, with the current code state?" "4406": "Are you using a memory manager?" "4411": "How are you laying out your levels currently and are you going to make a level editor?" "4460": "Is knowing Big O notation important in the game programming industry?" "4508": "You mentioned further ways of partitioning collisions past breaking it up into regions. What would some of those be?" "4556": "End that for today" --- name: "day079" title: "Defining the Ground" markers: "236": "handmade.h: Check the TODO list" "291": "Blackboard: The Ground" "345": "Blackboard: Quake vs. Unreal" "541": "Blackboard: Quake's "Constructive Solid Geometry" Paradigm" "639": "Blackboard: Unreal's "Constructive Solid Geometry" Paradigm" "741": "Blackboard: The difference between these two models" "865": "Blackboard: Robustness vs. Efficiency" "1015": "Blackboard: Propose not talking about "Ground" or "Floors", but "Rooms"" "1906": "Blackboard: What happens when you step off a ledge?" "2116": "handmade_sim_region.h: Add EntityType_Space entity_type" "2177": "handmade.cpp: Implement the ability to create an EntityType_Space" "2441": "handmade.cpp: Introduce AddSpace" "2824": "handmade.cpp: Rename AddSpace to AddStandardRoom and add EntityFlag_Traversable" "3049": "Blackboard: No overlap between adjacent rooms" "3100": "Run the game and see some giant rectangleS" "3143": "handmade.cpp: Turn off AddStandardRoom" "3195": "handmade.cpp: Correct the sim_entity_flags settings" "3242": "handmade_sim_region.cpp: Check EntityFlag_Collides in CanCollide" "3282": "Run the game and find that we now correctly don't collide with the StandardRooms" "3290": "handmade.cpp: Introduce PushRectOutline" "3397": "Blackboard: Drawing out the PushRectOutline" "3458": "handmade.cpp: Continue writing PushRectOutline" "3553": "Run the game and find that we cannot see the outline" "3566": "handmade.cpp: Increase the thickness of PushRectOutline" "3590": "Run the game and find that we're only drawing one line" "3607": "Debugger: Step into PushRectOutline" "3730": "handmade.cpp: Multiply the Dim by half" "3779": "Run the game and see our correctly drawing outline" "3825": "Q&A" "3907": "What setup do you use for debugging on Linux?" "4021": "Can you upload the videos somewhere else? YouTube is blocked in China. I would like to watch from the beginning" "4064": "When doing the vertical movement, would it be reasonable to take two measurements: one at current position, then one at "final moved" position, and average the movement?" "4107": "Are walls going to be entities, or just byproducts of the subtracting of the room volume?" "4140": "LLDB works better than GDB, if you can deal with the command line interface" "4180": "Should you have been able to jump up to a level above the player now that you have a .9 value for the Space Z volume?" "4224": "Will the entities not at the player's Z level always be at the same alpha transparency or will they be slightly less visible to show that they are on a different Z level?" "4314": "Why should anyone trust you to annotate a game when you have no published success preparing a full-fledged commercial game?" "4368": "If you were a software programmer, how many apps could you have done in the same amount of time you have put into this?" "4431": "Will there be water, and how would it affect movement?" "4486": "Reminder: Water that you can swim in, maybe with currents too?" "4516": "Does the system used for the ground now make it harder to have things like moving platforms the player can stand on?" "4530": "Reminder: Moving platforms the player can stand on" "4555": "Was the use of calculus involved in your programming?" "4602": "For this scheme, will the room geometries need to overlap in order to move between rooms, or can they just abut?" "4644": "Can you illustrate how they do the level editors / world layouts in modern engines now?" "4748": "Are you going to use files to store levels? If so, will they be custom format?" "4773": "Would the combat algorithm in a 2D game differ from a 3D game?" "4805": "How can I work with other programmers when our coding styles clash?" "4866": "Should there be walls around stairwells now, or will we still just use the collision rules from before?" "4889": "Are you going to procedurally build levels, or pre-defined levels?" "4903": "Will wee see stuff like light sources, ray tracing, surface mapping, etc. at some point in this stream?" "4941": "Have we started doing collision detection and handling? If no, how detailed will it have to be?" "4966": "What do you think about storing game data in code?" "5039": "So you will continue complaining about Windows while making money programming with it and Visual Studio?" "5430": "Can you rename the stream to Casey's Little Kindergarten?" "5458": "One day you said you lost hope in Microsoft, and now you say you complain so they can fix it?" "5638": "Was git an example, or do you feel there are problems with it? Curious to hear" "5742": "Call it there" --- name: "day080" title: "Handling Traversables in the Collision Loop" markers: "269": "Blackboard: Augmenting the collision loop to loop over two types of t value" "310": "handmade_sim_region.cpp: Introduce tMax" "358": "handmade_sim_region.cpp: Consider how best to modify this routine" "663": "handmade_sim_region.cpp: Loop over the Walls to get all of the data taken by TestWall" "915": "handmade_sim_region.cpp: Introduce test_wall" "956": "Run the game and make sure it's still working" "974": "handmade_sim_region.cpp: Embed TestWall directly in the collision loop" "1065": "Run the game and test the collision" "1132": "handmade_sim_region.cpp: Test tMax" "1323": "handmade_sim_region.cpp: Massage the routine" "1467": "handmade_sim_region.cpp: Implement the tMin vs. tMax logic" "1587": "handmade_sim_region.cpp: Write the tests for Overlap and EntityFlag_Traversable" "1689": "Encourage us not to be scared of solving complex problems" "1969": "handmade_sim_region.cpp: Improve the overlap test" "2157": "handmade_sim_region.cpp: Introduce EntitiesOverlap for this overlap test" "2322": "handmade_sim_region.cpp: Make EntitiesOverlap take an Epsilon enlargement region" "2406": "handmade_sim_region.cpp: Reenable the EntityFlag_Traversable test and use EntitiesOverlap" "2512": "Run the game and find that we can't get past our tMax" "2547": "handmade_sim_region.cpp: Move tMin, tMax and HitThis inside the loop" "2643": "handmade_sim_region.cpp: Rethink the logic of the collision routine" "2785": "Run the game and find that we're working a little more properly" "2804": "handmade.cpp: Only create walls in the first room in order to test the new world definition" "2827": "Run the game and test the collision detection" "3004": "handmade_sim_region.cpp: Increase the size of the overlap Epsilon" "3115": "Debugger: Step into the collision routine" "3243": "handmade_sim_region.cpp: Initialise tMaxTest to our current tMax" "3274": "Run the game and find that everything seems pretty good, but still a little janky" "3295": "Set the stage for next week" "3333": "Q&A" "3343": "Consult the TODO list" "3494": "Can you explain the LengthOf(array) macro, and the sizeof pointers?" "3979": "Will the space entities be used for the collision optimization you were talking about in an earlier stream? o(n^2) stuff" "4038": "sizeof(game_input::Controllers) works for me with g++" "4089": "I noticed that you tend to mostly skip over questions past the first question mark. Is it because you just parse that way or the rest tends to be not much interesting?" "4143": "For things like the projectiles, are we going to extend their bounding boxes in the Z axis so they will always hit enemies that are below them? Or are we going to handle that in screen space somehow?" "4204": "Do you dislike templates?" "4277": "How will you handle something like an explosion that affects all things in an area? Then it's not 1 entity colliding with another" "4329": "What do you think about the new Vulkan API?" "4395": "Wrap things up" --- name: "day081" title: "Creating Ground with Overlapping Bitmaps" markers: "19": "A regrettable incident..." "367": "Maybe we should try to add some sort of drawing to the ground" "433": "Viewing the art assets in GIMP" "672": "Casey's vision for the art" "910": "Load ground textures" "1052": "Introduce DrawTestGround to composite the textures" "1276": "Viewing the results in-game" "1305": "Randomly splat down a ton of grass textures" "1396": "Looking at RandomNumberTable" "1482": "Figure out the maximum value of RandomNumberTable" "1601": "...and the minimum value" "1691": "Produce a floating point number between 0 - 1 within the range of RandomNumberTable" "1784": "Blackboard: Transforming a number from being between 0 - 1 to between -1 - 1" "2045": "Blackboard: What happens in between two points?" "2246": "Blackboard: Degrees of polynomial" "2729": "Implement the equation f(x)=2x-1 and splat multiple grass textures" "2863": "Account for the centre of the bitmap" "2958": "Set the radius by which to offset the splats" "3065": "Provide a function to make a v2 out of integers" "3197": "Parameterise loaded_bitmap" "3490": "Restart the game" "3510": "Tuft it up" "3576": "Q&A" "3629": "On the fancy autoload dll stuff" "3712": "Q: Is there an art team working on this game?" "3761": "Max random number should be set to fixed number 100000[...] because in episode 35 when you went to random.org you chose to generate random numbers from 0 up to that number" "3831": "Obviously that wasn't a serious comment. But on-topic question: Do you want to mention tangents when designing curves?" "3880": "Would you ever actually use a higher degree polynomial interpolation? Aren't there better ways to make interpolating curves that are more stable?" "4433": "Q: What sort of optimisation would you do on that ground stamping?" "4576": "Q: You aren't treating both ends of the random numbers the same. With the current system you can get 1 but you will never get 0 because you are not considering the min..." "4709": "Q: Do you plan on having things like dirt paths and, if so, would you draw them using splats and stamps?" "4808": "Q: So your ground texture design is essentially MegaTexture?" "4869": "Q: Based on the stream, it appears that you need to know math to do this type of activity. Is that correct?" "4933": "Blackboard: Casey's Plan vs. MegaTexture" "5567": "Q: Why do you think John Carmack is a hack and when are you going to say it to his face?" "5766": "Conclusion" --- name: "day082" title: "Caching Composited Bitmaps" markers: "41": "Let's take a look at where things were" "132": "Toggle off the debug boundaries" "169": "Two things to look at: 1) Speeding up the texture splats and 2) Multiple layers" "256": "How to make the random number generation more systemic" "617": "Introduce random_series which takes a seed" "783": "RandomUnilateral (0 - 1) and RandomBilateral (-1 - 1)" "875": "Blackboard: Brief recap of yesterday's maths class" "918": "Introduce RandomBetween" "998": "Pass RandomChoice to the Stamp picker" "1037": "Make Seed function" "1103": "Implement the rest of the random number generation" "1345": "(Re)introduce Lerp" "1488": "Blackboard: Lerp or Linear blend" "1608": "Stick it in handmade_math.h and use it?" "1673": "Finish propagating RandomChoice" "1877": "Make a RandomBetween for use in integer space" "2025": "Find the Familiar" "2194": "Fix the FamiliarOffset range" "2366": "We've taken care of everything regarding the random number table" "2408": "Next: Try doing a pre-composite" "2469": "Look at how game_offscreen_buffer used to work" "2514": "Condense game_offscreen_buffer and loaded_bitmap down to one thing" "2747": "Set the Pitch and Pixel pointer from the Bitmap" "2917": "A small correction, and viewing the results" "2952": "Change DrawBitmap to take loaded_bitmap *Buffer, and change *Pixels to *Memory in loaded_bitmap" "3002": "Remove BytesPerPixel from game_offscreen_buffer" "3070": "Make everything take the data from loaded_bitmap" "3173": "Implement a GroundBuffer cache" "3360": "Implement MakeEmptyBitmap" "3622": "Set the alpha channel of the composited bitmap" "3885": "Recap today's work" "3974": "Q&A" "4022": "Q: Casey, I missed the earlier part of the feed, but what was the intention of moving the ground plane with the player?" "4057": "Q: Why aren't RandomUnilateral and RandomBilateral not just using the implementation of RandomBetween? Seems like a pretty clear violation of DRY, although I realise you aren't currently intending for this code to be extremely clean right now" "4279": "Someone wants a cloc count" "4331": "Q: Why does the Seed function not have a prefix or suffix Random?" "4434": "Q: Is it okay that RandomChoice doesn't select the random value uniformly? [...]" "4522": "Q: Wouldn't RandomChoice have a slightly uneven distribution if the number of choices didn't evenly divide the maximum random number?" "4639": "Q: When is it okay to pass larger objects like r3's by value instead of by reference?" "4921": "Q: Casey, just curious because the background tiles are static at the moment..." "4948": "Q: Do you see yourself extending RandomNumber to have anything other than a uniform distribution?" "5002": "Q: Is this strictly handled in RAM? Do you have plans to use GPU resources for rendering?" "5046": "Q: I notice in functions you will always use a Result variable even if the calculation is a one-liner, rather than using the expression directly in a return statement. Does this incur an extra copy and are there performance implications?" "5106": "Q: Do you plan to move all the other loaded_bitmap memory to be in a memory_arena as well?" "5137": "Q: I think you've used an aggregate initialiser in one place with random_series being seeded, i.e. you only have one call to RandomSeed but you have at least..." "5213": "Q: Initially, you put BytesPerPixel into the bitmap structure because it can be useful. Then I asked you to remove it because it never changes, and you did that. But ten or so episodes later you added it back because it would be useful. And now you're removing it again. This is funny" "5265": "Q: You fix Random to be uniform by generating a full 32bit random number, do mod next power of 2 choice count, then check if result is less than choice count. If not, repeat the whole process" "5298": "The end of another full-power episode of Handmade Hero, which was dedicated to Abner Coimbre" --- name: "day083" title: "Premultiplied Alpha" markers: "104": "Recap yesterday's work" "260": "Investigate peripheral problem" "361": "Blackboard: Alpha channel in the intermediate buffer" "608": "Blackboard: Considerations for handling alpha" "990": "The allergy of computing" "1028": "Blackboard: Alpha blend our edges" "1385": "Fuss with alpha" "1449": "Call DrawTestGround every frame" "1525": "Play with DrawBitmap" "1607": "Introduce real32 RSA in order to keep SA and DA in the same space" "1763": "Does that produce the result we expect?" "1818": "What GIMP thinks is a reasonable thing to have occur" "1918": "Play with the alpha channel of Stone" "2151": "Blackboard: What's happening with the colours?" "2447": "Blackboard: Pre-multiplied alpha" "3354": "Pre-multiply alpha" "3488": "Grab out each individual channel" "3651": "Do that pre-multiplication" "3858": "Blackboard: Brief recap" "3967": "Blackboard: Do the pre-multiplied alpha examples in algebra" "4299": "Blackboard: Have something in that screen to begin with" "4581": "Blackboard: Group the terms" "4933": "Blackboard: The equation for the pre-multiplied alpha" "5045": "Implement the equation" "5137": "Re-enable DrawTestGround" "5224": "Put CAlpha back in" "5413": "Check the equation" "5557": "Q&A" "5598": "Q: According to [a website], to fix the Wacom driver without restarting, stop and start Wacom Professional Tablet Service" "5700": "Q: Being Happy, Sleepy and Sneezy, you do realise you're just four dwarves short of a whole crew?" "5767": "So if I understand correctly (sorry if my interpretation just confuses anyone), the reason off-screen rendering was incorrect before pre-multiplied alpha was that, after blending, things in the texture - the colours there - were pre-multiplied because they were multiplied when they were put in the texture. If, for some reason, you didn't want to optimise your code, you could also divide the colour channel by the alpha to get it back to un-pre-multiplied. Is this a reasonable understanding of the issue?" "6175": "Q: Can you give a small example of what the decompression step between SimEntity and StoredEntity will look like?" "6204": "Q: Maybe we should set a way for you to see things like that kind of help, if someone finds a good possible solution. No, I don't know how" "6235": "Blackboard: A lot of equationing" "6283": "Wrap up the stream with a brief recap..." "6374": "...a peek into the future..." "6569": "...and closing remarks" --- name: "day084" title: "Scrolling Ground Buffer" markers: "96": "Damage Assessment" "157": "We are trying to figure out how to finish off our world construction" "263": "Think about how to handle the ground" "323": "Look at how we're currently specifying the ground" "409": "Blackboard: Our system for defining the ground" "636": "Blackboard: A potential plan and guiding principals of engine architecture design" "771": "Blackboard: How to store the splat list" "880": "Blackboard: Figuring out the shape of the ground" "1044": "Blackboard: Considering multiple Z-levels / depth" "1520": "Blackboard: Empty space things will carve out regions like that" "1639": "Blackboard: What are the splats for the region?" "1729": "Try to make the ground plane scroll infinitely in all directions" "1779": "Enlarge GroundBuffer, introducing MaximumZScale and GroundOverscan variables" "2125": "Partition the GroundBuffer so that we can scroll it around" "2164": "Blackboard: How the GroundBuffer is currently positioned" "2281": "Locate GroundBufferP relative to CameraP" "2591": "Plan to snap the GroundBuffer towards the camera's direction whenever it runs out of pixel coverage" "2613": "Turn off the trees" "2688": "Turn off Z doors" "2732": "Turn on the trees" "2760": "Make the ground constantly generate itself" "2828": "Blackboard: Tiling considerations" "2918": "Turn DrawTestGround into DrawGroundChunk" "3268": "View the results in-game" "3308": "Q&A" "3358": "Q: Why don't we fill the entire game window instead of having all that black space?" "3509": "Q: Are some of these issues with dealing with display on multiple levels stemming from the lack of a Z-coordinate for the camera to just do a lerp on?" "3663": "Q: If no one's asking related questions, could you ballpark a time-frame when adding a font and text rendering system will become useful or necessary?" "3782": "On learning C++" "3910": "Q: You mentioned offloading ground drawing to a separate thread to prevent hitches. Is it possible to offload the drawing work over multiple frames, and would there be any benefits over either method?" "3990": "Q: How much of a memory footprint is your game using already? Certainly it won't be large, but I'm more meaning how many different containers are there?" "4013": "Q: Procedural generation of 2D graphics: is there some mainstream math for that?" "4058": "Q: What is your programming experience as before Handmade Hero?" "4122": "Q: How many different classes are you having to use already?" "4230": "Q: Is there a simple way to explain pointers and references in C++?" "4590": "Closing remarks" --- name: "day085" title: "Transient Ground Buffers" markers: "78": "Recap of yesterday's repeating ground texture work" "138": "Blackboard: A smarter way to do things" "319": "Blackboard: Why don't we just make an array of tiles...?" "400": "Introduce TransientArena" "518": "Two memory areas: permanent storage and not-necessarily-permanent storage" "580": "Create that TransientArena" "621": "Allocate some space out of the TransientArena for the GroundBuffer" "707": "Make space for the array of empty bitmaps" "753": "Loop through them and allocate empty buffers" "834": "Provide the option to ClearToZero" "916": "Spec out GroundBufferHeight and GroundBufferWidth" "1011": "Put GroundBuffer into a loop" "1071": "How is the Bitmap aligned in the world?" "1137": "Find where the GroundBuffer is relative to the Camera" "1250": "Make sure that we're not drawing a GroundBuffer here if it isn't valid" "1316": "Which of our GroundBuffers actually has been getting used?" "1383": "Blackboard: Least Recently Used" "1631": "Look at what's in the structure" "1730": "Introduce GroundBitmapTemplate exemplar" "1881": "Limitations of the automatic dll-loading" "1946": "Debug GroundBuffers" "2015": "Owl of Shame Moment: There should have been a TODO about making the TransientArena do something real" "2062": "Blackboard: Memory partitioning schemes" "2336": "Introduce some way for us to use the memory in the TransientArena effectively" "2433": "Introduce transient_state" "2472": "Blackboard: What's in our stack?" "2547": "Transient initialization" "2807": "Pass the TransientArena to SimRegion" "2832": "Blackboard: Bungee back to the base line that was just after the GroundBuffer" "2869": "Let the Arenas do pushes and pops" "2889": "Insurance policy" "2915": "Implement the bungee and additional security" "3193": "Step through the code" "3294": "FillGroundChunk" "3480": "View the results in-game" "3551": "Q&A" "3575": "Q: What is the most expired food you have ever eaten?" "3591": "Q: Could you explain what pop and push are, and how they work?" "3689": "Blackboard: Memory is a big line!" "4249": "Q: How will the ground texture chunking handle adjacent rooms with different types of ground?" "4409": "Closing remarks" --- name: "day086" title: "Aligning Ground Buffers to World Chunks" markers: "230": "Recap" "254": "The Proposal: First, just produce tiles that cover things... but they won't be seamless" "358": "Address specifying which ground_buffer we need" "423": "Stop doing the test fill for GroundBuffer" "449": "Iterate over every place the camera can see and request a GroundBuffer" "783": "Blackboard: Offset considerations" "889": "Subtract the offset" "945": "Consider the size of a Chunk" "1123": "Brief interlude: See how big those Chunks are" "1672": "Try to view the results in-game and step through the code" "1779": "Multiply ChunkDimInMeters by MetersToPixels" "1868": "Make DrawRectangleOutline" "2292": "View the results and figure out what's happening with the Chunk location information" "2427": "DrawRectangle does not take a Width and a Height" "2486": "...and the Y needs flipping" "2531": "We're getting there, but the Chunks are drawn too tiny" "2566": "Assess the size of the Chunks" "2588": "Try making a Chunk a quarter the size" "2650": "Set the Chunk size based on the size of a 256*256 block" "2696": "Make MetersToPixels something integral" "2825": "Assess where TileSideInMeters gets set and consider doing without it" "2900": "InitializeWorld without TileSideInMeters and TileDepthInMeters" "2980": "Pass the ChunkDimInMeters directly in" "3091": "Introduce TypicalFloorHeight" "3128": "Set ChunkDimInMeters based on the value of MetersToPixels" "3203": "Derive WorldChunkDimInMeters from GroundBuffer{Width,Height} and TypicalFloorHeight" "3277": "Set Tile{Side,Depth}InMeters" "3339": "Do CameraBounds a little differently" "3365": "Introduce SimBounds based on the CameraBounds" "3455": "View the results in-game" "3543": "Request a particular world_chunk to draw" "3825": "View the results in-game" "3910": "Find out why those chunks aren't getting produced until the Hero walks on them" "4021": "This was working totally perfectly" "4073": "Problem solved" "4121": "Q&A" "4167": "Q: What is Muratori syntax?" "4232": "Q: Will the random ground splats be based on some seed so that the ground buffer can be regenerated the same as it was after it gets evicted?" "4273": "Q: I'm sure it's been asked a bunch, but any tips for what language to start with and how to start?" "4376": "Someone found a Muratori 'for' statement in the wild" "4475": "Q: Why are you not passing World as an address when calling functions?" "4501": "Q: Are you going to implement Z-buffers and texture scaling?" "4568": "Q: Is there any other possibility for a Z-buffer?" "4751": "Couldn't you set the SimBounds expansion from the screen dimensions or CameraBoundsInMeters or something? Hope I'm understanding it correctly" "4830": "Q: Will you be implementing dynamic lighting or any deferred rendering for lots of real lights, etc?" "4965": "Q: Is there anyone you can suggest for a hardcore render guy?" "5020": "Closing remarks" --- name: "day087" title: "Seamless Ground Textures" markers: "108": "Take a look at the state of things, but actually address a typo" "166": "Weird stuff can happen when you're using memory directly" "451": "Get back to what we were doing, i.e. making seamless ground tiles" "567": "Blackboard: How to get seamless tiles in" "792": "Loop over tiles in a 3 * 3 grid" "925": "Make sure that the Center accurately reflects that we're in a different Chunk area" "1011": "Blackboard: Center considerations" "1032": "Change the meaning of Center" "1150": "View the results in-game and review the code" "1197": "Correct the computation" "1232": "See where we're at" "1279": "Take another look at it and see" "1309": "Owl of Shame is peeking at us right now because we forgot to use the new Center" "1351": "We are now seamless across X, but not Y" "1378": "Turn off the tufts and take a look at what we're doing differently with the Y" "1455": "Consider the problem and try flipping the Y and X to see which one is done major" "1504": "What is wrong with our Y-handling?" "1542": "Our edges are probably lining up in the wrong order" "1565": "Check and see if that's the case (in-game)" "1658": "Tuft it back up" "1722": "Give it a little bit of slop" "1765": "Force us into a case where we run out of tiles right away" "1860": "Fill in each EmptyBuffer by reusing old tiles" "1928": "Keep the Chunk that's furthest from the camera" "2101": "Introduce Real32Maximum" "2146": "Find whatever Buffer would be best to replace" "2259": "Compile and review the code" "2408": "Let's see, it looks like 16 GroundBuffers is too few" "2514": "Do the detail splats last" "2630": "What should we do in 15 minutes?" "2689": "Make the code-reloading tell us when the code is reloaded" "2843": "Test the new and improved live code editing" "2907": "Casey is a little concerned that we're drawing too much..." "2940": "Shuffle the code" "2986": "Count how many GroundBuffers fit on the screen" "3016": "Assess our current situation" "3086": "Q&A" "3124": "Are the randomly generated floor tiles being cached yet?" "3140": "Do you think having things in place like static cast to put more checks, e.g. int to pointer, is useful over standard C-style cast which just ignores all type-checking? Wouldn't a static cast have found that bug at the start of the stream?" "3329": "Do you think the clumpiness is actually due to splat distance from the centre of the chunks?" "3440": "Do you know why the trees are wiggling around sometimes?" "3543": "What is causing the lag?" "3672": "Are there still places where the background colour shows through the ground tiles?" "3759": "Is this Chunk code already prepared for adding holes to the ground?" "4021": "Could you make code that ensures a certain frame-rate but uses extra available time to generate the ground textures in the background, maybe generating a low-quality version first to avoid having no texture at all?" "4138": "Recap, a glimpse into the future and closing remarks" --- name: "day088" title: "Push Buffer Rendering" markers: "37": "Investigate possible bug in the collision detector" "182": "Pass TestP to SpeculativeCollide and also base MoverGroundPoint off TestP" "207": "Make a version of GetEntityGroundPoint that takes ForEntityP" "276": "Walk around in-game" "300": "Put the stairs back in and try colliding with them" "359": "Increase GroundBufferCount from 32 to 64" "422": "Think about sorting entities in a render list and scaling bitmaps" "528": "Look at the TODO list" "571": "Create handmade_render_group.h" "593": "Consider sorting and translating the coordinate systems" "653": "Take a look at how the buffering currently works" "682": "Pull out entity_visible_piece and entity_visible_piece_group into handmade_render_group.h" "743": "#include handmade_render_group.h and handmade_render_group.cpp in handmade.cpp" "770": "Expand the notion of the PieceGroup so that it tracks everything" "871": "Move the rendering outside" "935": "Now all the pieces are in one giant buffer, and we have no idea which one goes with which entity" "967": "Introduce render_basis" "1026": "Enable setting the render_basis after moving the entities around" "1216": "Set the DefaultBasis and point to it" "1308": "View the results in-game" "1395": "Move PieceGroup up and give it its own memory" "1480": "Change all of the draw calls to operate off the PieceGroup" "1579": "Check it out in-game" "1599": "The inversion and scaling is all still happening erroneously" "1639": "Look at what the Push functions are doing" "1685": "Try and regularise how the rendering works" "1780": "See how it looks in-game" "1816": "Investigate why the Bitmaps aren't being drawn in the correct places" "2100": "It's drawing the same Bitmap" "2121": "Moment of realisation: Rather than sending the whole loaded_bitmap down, we were using one on the stack" "2192": "Consider ways to pass the correct Bitmaps" "2233": "Send the whole Bitmap to ground_buffer" "2335": "See if that fixes our problem" "2380": "Get rid of that other DrawRectangle call" "2431": "Rename entity_visible_piece_group to render_group" "2477": "Consider how we want to extend the notion of render_group so that you can have multiple things pushed onto this render stack" "2516": "Consider linked list vs packed set" "2563": "Add PushBufferBase, PushBufferSize and MaxPushBufferSize to render_group" "2632": "Introduce AllocateRenderGroup in handmade_render_group.cpp" "2718": "#define PushSize macro" "2740": "Allocate MaxPushBufferSize and store it in PushBufferBase" "2755": "Initialise all of the fields of the render_group" "2776": "Call AllocateRenderGroup and set MaxPushBufferSize to 4MB" "2812": "Make the DefaultBasis get allocated and initialise it" "2841": "Store MetersToPixels rather than GameState and pass it to AllocateRenderGroup" "2886": "Initialise MaxPushBufferSize and PushBufferSize" "2916": "Now we've got a problem: When we do PushPiece we can't get one because we don't know where that piece is anymore" "2924": "Attend to the other issues" "3011": "Straighten out the PushBuffer situation" "3247": "See if it works in-game" "3286": "Blackboard: PieceGroup" "3383": "Blackboard: Compression Oriented Programming" "3417": "Blackboard: render_group" "3499": "Q&A" "3556": "Will things like filters end up in the render_group?" "3655": "How long will the renderer take?" "3749": "Could you give us examples of what some of the simpler things will be in the render_group?" "3767": "Are there any static code analysis tools for C / Visual Studio that will help pick up bugs like unused variables, etc?" "3878": "So are you planning on abstracting away the renderer as a layer, similar to how we separated the platform from the game code, so that the various renderers will be operating on the same data structures?" "3948": "If you were going to write an algorithm to generate Sudoku puzzles, how would it work?" "3963": "Unused variables are a warning on my compiler. Did you turn that warning off? I use an allow local macro when I want it to ignore the variable" "4016": "Would it make sense for the render_group to contain render groups itself?" "4064": "I meant whether you plan for the data describing what needs to be rendered to be in a format such that it's suitable for both software and hardware rendering" "4125": "Will our hero always be taller than the treetops?" "4198": "We've finished early... or have we?" "4219": "Are we keeping the 5PM schedule?" "4326": "Wrap it up with a recap and closing remarks" --- name: "day089" title: "Renderer Push Buffer Entry Types" markers: "94": "Take a look at what happened on Friday" "236": "Blackboard: Rendering" "325": "Blackboard: Reasons for using a PushBuffer" "384": "Blackboard: History of game architecture built around the renderer" "421": "Blackboard: Modern day luxuries and trade-offs" "483": "Blackboard: Output Target" "584": "Blackboard: Balanced approach to optimisation" "665": "Blackboard: PushBuffer benefits" "781": "Blackboard: Considerations for supporting multiple targets" "856": "Blackboard: Our first target: Software 'GPU-esque Rendering'" "1020": "Blackboard: Two ways of looking at a render working: 1) Explicit Surface Rasteriser" "1102": "Blackboard: 2) Implicit Surface Rasteriser" "1179": "Blackboard: Reasons to use the Implicit method" "1196": "Blackboard: Something like how our renderer will look" "1247": "Blackboard: SIMD instruction sets" "1361": "Blackboard: Overview of what we're building" "1502": "Start pulling the Draw functions out" "1525": "Mini-rant on devenv" "1568": "Take a look at where we're at" "1587": "Start playing with the code" "1613": "Vaporise PieceCount" "1626": "Look at adding multiple types of commands in there, starting by renaming entity_visible_piece to render_group_entry" "1689": "Pull RenderGroupToOutput out into handmade_render_group.cpp" "1838": "Compression Oriented Programming" "1941": "Consider operating on groups of entities" "2058": "Setup cases for handling different types of Entry" "2127": "Introduce InvalidDefaultCase" "2165": "Increment BaseAddress depending on the Entry->Type" "2211": "Write those cases" "2273": "Create the corresponding render_entries" "2399": "Describe 'compact discriminated union'" "2543": "Review our new ability" "2637": "Ridiculous Trick: Prepend the type_name with RenderGroupEntryType to make the Identifier, and #define PushRenderElement macro for a type-safe way of correctly setting the type field in one step" "2752": "Pass the Type to PushRenderElement" "2814": "Compile and clean up" "2865": "Check all is still well in-game" "2878": "Create a bitmap type" "2963": "Call the PushPiece function for the bitmap" "2999": "Hit an assertion because the Entry->Bitmap is not filled in" "3010": "Make sure we push a rectangle on when we call the bitmap type" "3070": "Check that all is still okay in-game" "3106": "Compress the code down into something more usable" "3270": "Bake the offsets in to PushRect" "3504": "Pull out the EntityBasis computation" "3598": "Clean up" "3692": "See where we're at" "3698": "Q&A" "3795": "Warning! There may be lots of prestream questions today" "3837": "When you meet a bug in the game and are able to recreate it, will you get a bug line in the programming, or how does it work?" "3876": "Is it worth aligning render_entries?" "3951": "What is Mantle?" "3968": "Any recommendations of some reading about GPUs, rendering, rasterisation, except for a Google search?" "4143": "Why use pointers over references?" "4231": "About Mantle, were you aware AMD dropped development for it and put a lot of that manpower into helping push Vulkan?" "4283": "The PushBuffer is an abstraction layer relying on memory for communication instead of a bunch of functions, if I understand correctly. Is that how you prefer API design in general?" "4383": "We are done here" --- name: "day090" title: "Bases Part I" markers: "105": "Take a look at where we're at" "125": "Make lowercase the accessors for the vectors" "380": "Casey doesn't have enough Emacs-fu to bust that out" "540": "Find out if it worked" "570": "Resume work on RenderGroup structure, implementing Clear" "647": "Make DrawRectangle take A which defaults to 1.0f" "681": "Make the Clear call take its values from render_entry_clear" "717": "Make Clear function" "761": "Change R, G, B, A in render_entry_clear to Color" "774": "Cleanup" "787": "Review progress and glimpse into the future" "819": "Ensure that everything's working in-game" "840": "Turn off the GroundBuffers and the 'conditional expression is constant' warning" "905": "Consider what we haven't moved over into the renderer (Outline calls) and note that FillGroundChunk calls the bitmap routines directly, rather than the renderer" "960": "Put PushRectOutline and DrawRectangleOutline into the renderer as more specific concepts" "1184": "Run, crash and update PushRectOutline" "1233": "View the results in-game and add back in the Space lines" "1297": "Make FillGroundChunk go through the renderer" "1379": "Introduce GroundRenderGroup" "1416": "Let FillGroundChunk use the RenderGroup" "1544": "Put in a Clear to verify that things are actually happening" "1586": "Change DrawBitmap to PushBitmap and make it use that renderer syntax" "1612": "Consider supporting pixel positioning" "1714": "View the splatting in-game" "1732": "Cheese the pixel positioning by replacing MetersToPixels with 1.0f" "1774": "Showcase the live code editing by scaling the placement of the ground elements" "1865": "Blackboard: Introduce the concept of coordinate systems and bases" "1975": "Blackboard: How we measure, using the dot product" "2064": "Blackboard: Axes tend to have two properties: 1) Unit length" "2163": "Blackboard: ...and 2) Orthogonal" "2193": "Blackboard: Linear independence" "2293": "Blackboard: Forget about linear independence" "2352": "Blackboard: Orthogonality" "2568": "Blackboard: Linear independence" "2680": "Blackboard: There's linear algebra afoot here" "2694": "Blackboard: See why these are important properties" "2726": "Blackboard: 3D coordinates" "2834": "Blackboard: Basis vectors" "3011": "Blackboard: Basis changes: 'MetersToPixels' and 'negate y'" "3330": "Blackboard: Pretend we had some third universal basis" "3449": "Blackboard: How does Casey move a point from world space into screen space?" "3677": "Blackboard: Preview what we're going to do" "3788": "Q&A" "3821": "Would you represent the origin of coordinate systems in a universal coordinate system?" "3985": "A few streams ago you said you'd prefer to call functions through a macro and then forgot to explain why" "4026": "Why is the familiar moving left to right, or did I miss something?" "4052": "Why are computer coordinates upside-down?" "4350": "How important is it to know how to make a game engine vs simply using one? And if you were to use DirectX libraries, how much would the code differ?" "4866": "Wrap it up with a brief recap and a glimpse into the future" --- name: "day091" title: "Bases Part II" markers: "54": "Blackboard: Clarify linear independence" "138": "Blackboard: Bases" "376": "Blackboard: What does it mean to say we have an origin?" "466": "Blackboard: Consider describing origins and basis vectors in terms of other origins and basis vectors" "712": "Blackboard: Why do I care about this at all?" "732": "Blackboard: Rotation and scaling" "854": "Blackboard: Example rotation" "909": "Blackboard: Example scaling" "963": "Blackboard: What does that look like in code?" "1188": "Blackboard: This is what we'd like to introduce into our renderer now" "1220": "Blackboard: How do we define the X and the Y axis? (Unit circle)" "1481": "Blackboard: A handy optimisation thanks to being in 2D" "1699": "Blackboard: You can also directly plug and chug this" "1741": "Blackboard: Perp operator" "1869": "Blackboard: All we have to do" "1946": "Go into the code and create one of these rotating doodads" "2178": "Run the game to discover that our code is hosed" "2241": "See what our InvalidDefaultCase says" "2278": "Let it hit the InvalidDefaultCase sooner" "2314": "Take a look at the RenderGroup buffer" "2392": "Step through the code with an eye on PushBufferBase" "2441": "Moment of realisation: render_entry_coordinate_system was missing its Header" "2517": "Put our coordinate_system back in there and run again until it hits the InvalidDefaultCase" "2542": "Put in a case for our coordinate_system" "2632": "Define the coordinate_system to be something that's visible" "2772": "View the results in-game and apply transforms" "2867": "Edit this coordinate system live" "2934": "Insert some points that are encoded in that axis" "3099": "Check it out in-game (...or not)" "3146": "Moment of realisation: It'd be nice if Casey actually used PIndex" "3158": "Try viewing again" "3184": "Step through the code watching the coordinates of the Points" "3207": "Reduce the number of Points and view it in-game" "3259": "Play with those axes" "3326": "Do we have pie?" "3368": "Continue playing" "3447": "Q&A" "3566": "Do you usually worry a lot about naming schemes? You always seem to choose a good enough name and move on" "3588": "Is that the variable?" "3610": "How can you draw so fast? Do you use a draw pad and pen?" "3623": "I only partly followed, but it seemed fairly easy to get the basic rotation up and running. I'm wondering how much more work it will be to start rendering textures by sampling them across the plane" "3681": "Is it possible to do realloc with memory_arena?" "3737": "Are parametrics and polar functions going to be used later on?" "3786": "Will subpixel positioning and anti-aliasing be part of the software renderer in the exploration phase?" "3852": "Make the size proportional as well" "3920": "Go nuts with that" "3955": "Time-dependent colour" "4031": "Needs more dots" "4060": "Call it done for the day, with special mention made of that weird pulsating thing and a glimpse into the future" --- name: "day092" title: "Filling Rotated and Scaled Rectangles" markers: "23": "Recap of people egging Casey on to do some weird sine-cosine-theta stuff" "96": "Blackboard: Introduce effects" "279": "Blackboard: How do we do this rotation and scaling?" "329": "Run the game" "351": "Clip away all this ridiculousness" "392": "Look at the coordinate system" "433": "Blackboard: We need to know which pixels will be included as a result of rotating a rectangle" "515": "Blackboard: How the collision detection system may be applicable to pixel filling" "591": "Blackboard: Ignoring rotation and scaling for now" "754": "Blackboard: Iterating over the pixels" "824": "Look at the DrawRectangle routine" "862": "Write a function, DrawRectangleSlowly, that does DrawRectangle in the least efficient way possible" "1003": "Draw a rectangle that's at the origin of the CoordinateSystem" "1091": "See the results in-game" "1103": "Stop it rotating for the moment" "1121": "Check the scaling of the axes" "1194": "DrawRectangle after the fact in a different Color" "1231": "Note that the rectangle is not properly clipping to its max bounds, and rectify this" "1271": "Moment of realisation: We were adding Entry->Origin twice" "1287": "We're filling correctly but inefficiently" "1318": "Consider restricting the area that DrawRectangleSlowly marches over" "1341": "Blackboard: How does that help us do our rotation and scaling?" "1405": "Blackboard: Can't we just test against four corners of our rectangle?" "1475": "Blackboard: How we could have done that without Casey's help" "1735": "Implement one of these edge tests" "1790": "Make DrawRectangleSlowly take all of the coordinate system information" "1857": "Make DrawRectangleSlowly do the edge tests using the dot product" "1938": "Blackboard: Rephrase these edge tests" "1977": "Turn the test around" "2043": "Notice that, because we're not doing the dot product, the sign doesn't flip" "2073": "Make greater-than be our standard" "2103": "Blackboard: Think of the surface normals pointing outwards" "2120": "Change all of those edge functions to be negative" "2170": "Get the dot product in there" "2203": "Blackboard: What are the vectors of those perpendiculars?" "2249": "Implement those vectors" "2320": "Now we're doing the full test, see how it looks in-game" "2339": "Consider changing the edge tests to use the edges of the rotating coordinate system" "2360": "Blackboard: How to use those edges" "2382": "Get rid of vMin and vMax in readiness to use those edges" "2397": "Blackboard: Our tests" "2435": "Implement those tests" "2531": "Compile and view the results in-game" "2568": "Change the scale over time" "2584": "Blackboard: Optimising these tests" "2652": "Implement optimised exclusion tests" "3020": "Fix a couple of things, but not before filling everywhere in the bounding region" "3058": "Check the code" "3100": "Find our typo and restore our buffer pre-step" "3135": "Re-enable our edge test and consider further work" "3188": "Q&A" "3234": "What are your computer specs?" "3314": "Is it weird that I got really excited once the rotated fill got faster?" "3366": "Would skewing the axes still work?" "3457": "Implement a proper perpendicular" "3578": "Blackboard: How we want the Perp to work" "3626": "Make that Perp work" "3673": "Is downscaling bitmaps correctly slower than upscaling (more colour points to blend)?" "3705": "Blackboard: Downsampling and upsampling bitmaps" "3845": "Blackboard: Mipmaps" "3933": "Eventually, will you implement anti-aliasing into the rendering of the rectangle, or is that too much for the CPU?" "3967": "Blackboard: Texture sampling handles anti-aliasing for the alpha'd bitmaps" "4077": "Check out our hilarious little shape and review our progress" "4177": "Historically, did we ever do anti-aliasing with CPU rendering?" "4312": "Postpone anything more until tomorrow, with a potential plan of action" --- name: "day093" title: "Textured Quadrilaterals" markers: "44": "Recap and push forwards" "166": "Expand the notion of CoordinateSystem to allow passing a Texture" "276": "Review how our Edge equations work" "365": "Blackboard: Working through a problem from first principals" "446": "Blackboard: Texture mapping" "562": "Blackboard: Standard nomenclature" "736": "Blackboard: How do we produce some u and v values that tell us where in the texture we are at any given time?" "906": "Blackboard: Take a look at what's going to happen here" "1058": "Blackboard: Does this equation give us what we want?" "1170": "Blackboard: Looking at the problem from another angle" "1281": "Blackboard: The equation we'd like to implement" "1336": "Implement that equation, starting by distributing the negative in the Edge tests" "1369": "Introduce d" "1396": "Compute u and v" "1499": "Lookup the u and v inside the Texture" "1668": "Compile and see what's happening in-game" "1675": "Assert that X and Y are >=0 and < Texture dimensions" "1700": "Do that lookup of the u and v" "1776": "Check out our texture mapping in-game" "1824": "Add in the Alpha" "1916": "See the alpha composite happening in-game" "1943": "Slow down the fanciness" "1973": "Hit an assertion and postpone clamping U and V until we're doing SIMD" "2022": "Resume slowing down that fanciness" "2064": "Notice the flickering and mention subpixel accuracy" "2126": "Make the Tree bigger and put it in the centre of the screen" "2177": "Move the Tree horizontally and keep its angle constant" "2259": "Observe the nature of rendering without subpixel accuracy" "2336": "Blackboard: The number of pixels and texels isn't dividing out evenly" "2496": "Start tackling these problems" "2517": "Notice that DrawRectangleSlowly is ignoring the floating point accuracy that was passed to it" "2608": "Why do we still look like that, though?" "2638": "Blackboard: Doing a better job of figuring out where we are in the texture map" "2838": "Linearly blend (Lerp) the colours" "2935": "Pretend our Texture is smaller than it actually is" "2979": "Blend these guys together, but not before lofting out the Color values" "3181": "Manufacture a v4 for Lerping between two Lerps and ones for doing scalar multiplications" "3287": "View our properly blurry rendering in-game" "3415": "Switch between the old and new ways, for comparison" "3553": "Q&A, after getting the tree spinning again" "3653": "Will the Wall trees be subpixel accurate now?" "3697": "the top of the tree seems to be cut short" "3830": "Is tree spinning going to be in the DLC?" "3854": "does it rotate with subpixel accuracy?" "3918": "What's the most major / fundamental thing left to do on the renderer?" "3969": "TODO(casey): SSE clamping" "3987": "Q: how would you do smooth subpixel rendering for something like pixel art graphics, that doesn't blur but still moves smoothly" "4019": "Blackboard: Doing smooth subpixel rendering for pixel art graphics" "4329": "couldn't you use the rounding +0.5 and truncate to not sample outside the edges of the texture?" "4411": "why are you still adding 0.5f to tX and tY?" "4428": "Is it any faster if you just test the domain of (u,v) instead of testing edges?" "4557": "Is rendering on the cpu different in comparison to rendering on a gpu codewise?" "4639": "Are there performance benefits for using a quad as primitive over triangles in a software renderer like this?" "4739": "why do the edges of the tree look like they are feathered?" "4794": "Will the different renderers be in the platform layer?" "4819": "I saw a great video on youtube called 'Computer Color is Broken' from minutephysics that talks about how blending colours is usually incorrectly done. Without relying on 3rd party libraries, you have an opportunity to do it correctly." "4941": "Remember when you introduced RenderGroup the other week? Is this subpixel rendering lerp one of the things that will go in the RenderGroup?" "4996": "Call it for today with a recap and a glimpse into the future" --- name: "day094" title: "Converting sRGB to Light-linear Space" markers: "67": "Recap last week's work on the renderer" "98": "Won Chun's request: Correct gamma correction" "248": "Chart: Gamma curve of Casey's monitor" "392": "Blackboard: Gamma" "518": "Blackboard: Why does Won care?" "741": "Blackboard: We'd need to undo or, rather, account for the effects of the monitor's gamma curve" "936": "Blackboard: How do we do it in a software rasteriser?" "967": "Internet: sRGB definition" "1056": "Internet: Gamma correction" "1103": "Internet: Filmic Games: 'Linear-Space Lighting (i.e. Gamma)' by John Hable" "1215": "Blackboard: What the gamma curve is generally expected to be" "1336": "Blackboard: Computing that gamma curve" "1412": "Blackboard: Envisioning the Framebuffer pipeline" "1564": "Blackboard: Caring about bandwidth" "1714": "Internet: 'Uncharted 2: HDR Lighting' slides by John Hable" "1746": "Blackboard: We want to mimic what the monitor is doing" "1805": "Implement this sRGB approximation" "2173": "Create the SRGB255ToLinear1 and Linear1ToSRGB255 functions" "2349": "Compile, take a look in-game and go through that with a more fine toothcomb" "2649": "Set a breakpoint and step through the code" "2870": "Moment of realisation: Linear1ToSRGB255 was multiplying by 255 before square-rooting" "2897": "Enjoy our tree in all its gamma corrected glory" "3061": "Start using the Color value to tint our texture maps" "3103": "Blackboard: Tinting" "3131": "Implement tinting" "3187": "Live tinting" "3337": "Premultiply the alpha properly" "3428": "Blackboard: Premultiplied alpha" "3549": "Q&A" "3577": "What would be the visual artifact of using 2 instead of 2.2 for the gamma?" "3688": "Q: Also need to do additive color tinting for full expressiveness" "3731": "I have a CS background but am 2 months behind on coding this. It is much easier to follow when I'm not trying to type myself. How detrimental would it be to my understanding to watch and just stop coding if I get too far behind? Sometimes when you're moving things around, I have to watch that bit 2-3 times" "3798": "Would it be worth only using gamma correction on texels that have alpha not equal to 0 or 1?" "3837": "Could we do our maths in sRGB space?" "3862": "Blackboard: Lerp in sRGB space" "4109": "Blackboard: This Q&A just turned into an exploration" "4240": "When are you going to start implementing OpenGL for the rendering?" "4260": "Wouldn't be the 10_10_10_2 format (which is also available in hardware) be sufficient to avoid banding?" "4325": "Then what is the point of using 2.2 at all? Why not just use 2 for the gamma?" "4378": "By repeatedly converting between linear and our approximated gamma space when doing each blend, are we compounding our errors?" "4487": "Do all monitors use the same 2.2 curve?" "4583": "Is raising the color value to 2 instead of 2.2 really going to save that much processing power?" "4691": "I got stuck implementing a Bitshift + PRNG in your engine, thanks for showing a code comment about 'Wang Hashing' earlier which was just what I needed" "4726": "Wrap it up for today" --- name: "day095" title: "Gamma-correct Premultiplied Alpha" markers: "80": "Recap yesterday's work" "160": "When do you premultiply the alpha?" "298": "This bilinear blend might want to be in premultiplied alpha" "405": "Inspect the change in appearance of the tree" "524": "See if we're storing the Texels premultiplied (we are)" "564": "We are not doing the most correct thing" "607": "Do not premultiply the alpha at all" "651": "Multiply the alpha just before the blend" "700": "On the output our Color values want to be not premultiplied" "752": "What happens on repeated blends?" "855": "Blackboard: When our values aren't stored premultipled" "1004": "Blackboard: Projecting back to sRGB" "1087": "Project the Color values back to sRGB space before storing them" "1198": "Add struct containing rgb and a" "1260": "Check it out in-game and consider making all our routines gamma-aware" "1363": "Convert DrawRectangle to handle gamma correctly" "1730": "Try and check it out in-game" "1792": "Think about making our software renderer run relatively quickly" "2007": "Take another look at DrawRectangleSlowly and premultiply the Color upfront" "2219": "Do a little bit of cleanup" "2318": "Blackboard: How the Header worked" "2365": "Do two sequential pushes of the Header and Data" "2486": "Step through that and make sure it works" "2572": "Increment the BaseAddress properly and check it out in-game" "2698": "Consider pulling out the Draw functions into a seperate file" "2796": "Internet: MSDN: 'optimize'" "2873": "Try using #pragma optimize" "2997": "Internet: MSDN: 'Optimization Best Practices'" "3052": "Try wrapping everything else in a #pragma optimize off" "3265": "Q&A" "3339": "Why can't you compile OpenGL code to C to make a software renderer?" "3360": "Is it useful to be able to debug with optimizations on? Do you think you might be able to show how to do that at some point?" "3400": "Demonstrate /Zo compiler flag" "3698": "GLSL" "3948": "Should the Load Bitmap function also be optimized after making changes today to do premultiply?" "3983": "How would something like a dynamic array in this memory system work? Something that is persistent across frames, but able to change size. Holes are not possible in the memory arenas right now?" "4084": "Couldn't a compiler translate the OpenGL commands to C commands and wrap them in a loop which iterates over the pixels?" "4234": "Could you explain us how you free all the memory stack when closing the game?" "4256": "I have a hard time understanding why sRGB conversions are required for the alpha channel at all, and why your intitial code wasn't correct. The alpha channel is being used to just represent a proportion of photons from one source and a proportion of photons from another source(s). Wouldn't that be outside of the purview of color curves because it doesn't technically have anything to do with brightness?" "4299": "You seem to be manipulating colors on a low level. How are you pushing pixels? Sorry, I am kinda new" "4347": "Any reason why you write 'Texel.a + Dest.a - Texel.a*Dest.a' instead of just 'InvRSA*Dest.a + Texel.a', which would match the RGB channels?" "4374": "Rearrange these calculations and keep on keeping on condensing" "4554": "Wasn't the alpha channel authored with nonlinear colors?" "4592": "Call it a day" --- name: "day096" title: "Introduction to Lighting" markers: "119": "Consider addressing the problem of speed and optimisation in order to ease debugging" "242": "Two possible directions: Renderer Features..." "311": "...or Lighting Control" "386": "Suggest turning off everything except for the tree" "449": "Review what's going on in handmade_render_group" "498": "Turn off DrawBitmap, change the hideous pink background and switch to compile in debug mode" "603": "Stop the tree rotating" "650": "Blackboard: 'Lighting is the sound of graphics' - Doug Church" "833": "Blackboard: Dynamic lighting" "932": "Blackboard: Lighting is fundamentally a 'directional' effect" "1062": "Blackboard: Wavelengths" "1284": "Blackboard: RGB colour receptors" "1469": "Blackboard: Don't talk to animals with more color wavelength sensors than you" "1511": "Blackboard: We see the aggregate effect of all of the light sources scattering light towards our eye" "1604": "Blackboard: Subsurface scattering" "1692": "Blackboard: What makes surfaces look different?" "1957": "Blackboard: What sorts of surfaces do we tend to actually want?" "2110": "Blackboard: Approximations" "2309": "Blackboard: 'Light probes' or Indirect light sampling" "2662": "Blackboard: What do we do in 2D?" "2782": "Blackboard: Normal maps" "2899": "Blackboard: We don't know what the light field is" "3199": "Q&A" "3258": "So is this why animation studios like Pixar have super computers for the rendering?" "3331": "What about shadows?" "3369": "Blackboard: Shadow maps" "3481": "I was looking for a build design doc to follow if you have one?" "3508": "Do we also plan on having a day/night cycle and dynamic shadows, where they stretch and fade depending on the position of the sun?" "3576": "Light feathering, e.g. in a window or tree" "3601": "Sort of on topic would you consider doing a true 3D lighting and or ray tracing discussion/lessons at some time?" "3624": "How do you account for infinite reflections if there is a mirror that reflects light into a mirror that reflects light back at the first mirror?" "3708": "Blackboard: Volumetric scattering" "3783": "Could you repeat that?" "3792": "Q: Heated debates of why we need to go through the trouble you're going through. #JustUseUnity Many newcomers" "3986": "Is 2D worth going for when it becomes more complex than 3D?" "4162": "Is your 'lighting cube' idea the same thing as cubemaps?" "4244": "How to feather light through a window or tree" "4267": "Blackboard: Translucence" "4456": "Why don't we just have the lighting feigned on the sprites?" "4516": "How about the second framebuffer you mentioned with light sources having precomputed distance falloff, plus graphics objects having another channel similar to alpha that indicates reflectivity? That would be fast and maybe good enough for a 2D game" "4551": "Blackboard: Illumination is constant along a line" "4714": "Due to the complexity of lighting, are system resources a major factor/consideration in shading engines?" "4750": "If you use a 2D lighting buffer, will you need to generate a G-buffer or Z-buffer as well first?" "4787": "What about bleeding effects?" "4795": "Is this going to work with software rendering or will it be too computationally expensive?" "4837": "You mentioned computing values for a single source receiving light from multiple sources. How would we in essence do this computation? I'm assuming it's based off of neighbouring pixel values. I'm having a hard time formulating an approach" "4929": "Wouldn't it (in most cases) be smarter to use an existing graphic / render engine and just focus on coding the game itself / gameplay?" "5103": "What is the ambient occlusion and why my video card get late to run games with ambient occlusion? Like really lose FPS" "5129": "Blackboard: Ambient occlusion" "5507": "Do you prefer cake or muffins?" "5519": "Do you have any plans to implement sprite opacity and, if so, could it be taken into consideration with the light map calculation, i.e. less opaque objects block less light?" "5560": "Are there any books or resources you would recommend on lighting or game engine creation in general?" "5631": "So game design documentation, like a roadmap for the game?" "5667": "Wouldn't a game in pitch darkness have the easiest lighting system to code?" "5719": "Can you go back in time and start this series 15 years ago?" "5752": "If you did choose cake, would it be a cheese or mud cake?" "5765": "What I mean is sort of more like how to make beams of light pass through a rendered object" "5784": "Blackboard: God rays" "6108": "Don't you cast rays from the eye and not the sun to reduce calculations, and then see if the rays cast from the eye hit the sun?" "6206": "Can you use a 3D overlay to pretend, say, a slice of a 3D environment. For example, the platform you are on being z, and then x is across, y up and down. So you can have a light source at x 33, y 50, z 1. So all objects less than x 33 would be shadowed to the right, objects greater than would be shadowed to the left, greater than y 50 would be brighter to the front and less would be shadowed to the back... I don't know if this is making sense, but would it be possible?" "6253": "In early episodes you worked on having multiple z levels. Wouldn't this mean you would need to render walls in 3D, thus introducing some 3D into the rendering and lighting calculations?" "6282": "How often do you stream Game Development?" "6312": "What is your background that led to where you are? Is education important or interest more important?" "6326": "Will this lighting system work for blind people?" "6349": "Do you think we'll be able to do all this in real time or will we have to pre-bake some of the lighting information when generating the map?" "6371": "Couldn't you just make a 3D game and then flatten it with a rolling pin?" "6389": "How often is real time radiosity used in games? Is it easy, and do you guys use it? Why or why not? Any hints?" "6486": "I saw a game that uses normal maps on sprites" "6519": "Isn't lights falloff inverse square? As you move farther from the source each ray is further from its neighbors" "6535": "Blackboard: Inverse square law" "6696": "Would you consider voxelizing the scene like Little Big Planet 2 does?" "6766": "Had to log in so hopefully this isn't too late. Wouldn't there be falloff with a point source when integrating across the surface, since the rays spread out away from the source?" "6873": "Why is it easier to represent light as photons and not particles in 3D programs?" "6908": "Rendering light in environments and events approaching the speed of light. How to do it?" "6924": "PBR lightning? Quick run down on how it works?" "6941": "We have come to the end" --- name: "day097" title: "Adding Normal Maps to the Pipeline" markers: "137": "Recap yesterday and plan for today" "175": "Blackboard: Normal maps" "328": "Blackboard: The importance of Normal" "414": "Blackboard: What we need in order to compute lighting based on this Normal" "507": "Blackboard: Where the Normal map fits into the equation" "731": "Blackboard: Description of the surface" "872": "Blackboard: Description of the light" "1018": "Blackboard: Casey's proposal" "1312": "Blackboard: Blurring based on the surface description" "1528": "Introduce the concept of a NormalMap" "1614": "Blackboard: Normals have to be Normal" "1761": "Introduce Unpack4x8 and unpack the Texels" "1880": "Similarly unpack the Normals" "1936": "Blackboard: We often bake the description of the surface into the Normal map" "1991": "Lerp the Normals" "2035": "Introduce environment_map" "2242": "Set tEnvMap from Normal.Z" "2342": "Blackboard: We might want to switch nearer to 0.25" "2385": "Setup the environment_map lookups" "2656": "Create ScreenSpaceUV" "2770": "Pass that ScreenSpaceUV to SampleEnvironmentMap" "2810": "Check if there is a NormalMap" "2833": "Pre-light the Texel" "2873": "We haven't talked too much about how you compute lighting equations, per se" "2912": "Take SampleEnvironmentMap and return the Normal for now" "3079": "Plumbing" "3214": "Check it out in-game and generate a NormalMap to play with" "3288": "Blackboard: The NormalMap that we're going to create" "3321": "Implement MakeSphereNormalMap" "3498": "Blackboard: Think this through a little more" "3564": "Throw in a Normal.z calculation for now and finish MakeSphereNormalMap" "3763": "Add Normalize to handmade_math.h" "3829": "Compile and see it in-game" "3858": "Q&A" "3902": "Your 2D art already seems to have some shading. Will that just represent ambient lighting when mixed with this dynamic lighting you're trying to do?" "3957": "In MakeSphereNormalMap, should 'Y < Bitmap->Width;' be 'Y < Bitmap->Height;'?" "3975": "How far do you think you can increase the capabilities of an engine like this before you start to suffer from performance constraints due to using only the CPU (vs GPU)?" "4077": "Don't you need to SRBGToLinear1 the normals or use the normals instead of the texel in the lerp?" "4184": "Normal.z = Sqrt(1.0f - Normal.x*Normal.x - Normal.y*Normal.y);" "4325": "Is your lighting lookup a similar technique to MatCaps used in other software?" "4340": "What benefits do you see from using the extra time it takes to create your own engine from scratch? Is it worth it in your opinion?" "4355": "The catch is that it's going to take the Sqrt of a negative number if you're outside the sphere" "4443": "We have come to the end of the questions" --- name: "day098" title: "Normal Map Code Cleanup" markers: "103": "Off we go with a bit of a recap" "231": "Talk about MakeSphereNormalMap and GPU vs CPU renderer" "294": "Make TreeNormal for MakeSphereNormalMap to use" "443": "Get the game running, look at the unpacking of the NormalMap and change the way that it's packed" "545": "Blackboard: Consider the hacky nature of the problem" "698": "Blackboard: The Ground's normals" "843": "Handle front-facing bitmaps for now, starting by introducing UnscaleAndBiasNormal" "981": "Check it out in-game and look back through the code" "1048": "Draw just the Normal and force Texel.a to be 1.0f" "1097": "Step through the NormalMap code" "1154": "Moment of realisation: We were still sampling out of the Texture" "1183": "Continue stepping through the code" "1303": "Moment of realisation: Usually you want to move to the next Pixel when you write one" "1333": "Quickly check the maths" "1372": "Blackboard: Nz should be Pythagorean theorem solved" "1479": "Calculate Nz" "1511": "Set the Normal and look at how the Pixels are packed" "1588": "Step through the code" "1612": "Blackboard: Dealing with the area outside the sphere" "1655": "Introduce RootTerm" "1745": "Check the values of the Normal" "1795": "Take a look at it in-game and find some erroneously negative values" "1900": "Owl of Shame Moment: Yesterday's code was awful" "1934": "View the correct NormalMap" "1968": "Recalculate Texel.rgb such that it is within the valid range of colours" "2063": "Turn off the NormalMap and consider using something more defined than the tree bitmap" "2095": "Temporarily draw TreeNormal as if it was a texture map" "2162": "Set the Pitch correctly and introduce BilinearSample function" "2347": "Check it out in-game and switch to the path in which the NormalMap modulates the texture" "2389": "Light the texture with the NormalMap" "2482": "Take a look at it in-game" "2508": "Tackle the environment_map stuff" "2724": "Blackboard: Picking from the environment map" "2871": "Nullify the Middle sample and make SampleEnvironmentMap produce values we can use" "3333": "Look forward to next week" "3388": "Q&A" "3462": "Recap today's cleaning up" "3501": "When you lerp two normals, you probably won't get a normalised vector. There are a few things you can do about that. Would you briefly comment on your thoughts about this?" "3701": "Q: how are we going to sample lights when calculating the pixel values for each sprite? Will there be a list of all the lights? Or will that be a parameter of some sort?" "3730": "What ever happened to your almond milk?" "3747": "Will Yangtian be making normal maps for the art now too?" "3771": "Will you cover more advanced BRDFs? Or just simple phong-like lighting equations?" "3888": "What if I don't want my game to be just 'normal'? Are there any other kinds of maps I can use to make my game more unique?" "3985": "Q: Some games use a 'bump-map' in addition or instead of a normal map. What is the difference between these and what are the advantages or disadvantages?" "4032": "Blackboard: Bump Map vs Normal Map" "4357": "gasto5 Q; Will the effect end up like a bump map effect?" "4374": "Could we do reflections by using our frame buffer as an environment map when drawing the bitmap?" "4397": "If you imagine the surface as an implicit function f(x,y,z) = 0, it's the gradient of THAT function. Which is the same as the cross product of the two surface tangents." "4484": "We have come to the end of the questions" --- name: "day099" title: "Test Enviroment Maps" markers: "147": "Blackboard: Make some light fields" "467": "Create test environment_maps" "598": "Initialise environment_maps" "711": "Setup the LOD (Level of Detail) picker" "815": "Pass the maps to CoordinateSystem" "867": "Compile and clean up" "938": "Run and get nothing in particular happening" "966": "Draw the EnvMaps" "1376": "Prepare the EnvMaps" "1566": "Check it out in-game" "1602": "Note the bugs and extol the virtues of structured art" "1740": "Look at fixing the sampling of the Bottom map" "1889": "Prioritise straightening out the coordinate systems" "1945": "Fix that sampling of the Bottom map" "2103": "Math is right even when you're wrong" "2116": "Implement a checkerboard pattern for the EnvMaps" "2403": "Implement ToV4" "2455": "Continue with the checkerboard routine" "2632": "View the checkerboard in-game" "2696": "Introduce TestDiffuse and TestNormal" "2845": "Take a look in-game and change the colour of the background" "2888": "Take a look at what we were doing in SampleEnvironmentMap" "2920": "Use the Normal to look up into the environment_map" "2965": "View it in-game" "3035": "Q&A" "3090": "In the MoveEntity function you have two variables that are never used: NewPlayerP and OldPlayerP. Will you delete them for me?" "3148": "Would this scheme let you have a pool of water reflect a starry sky?" "3205": "Blackboard: Reflecting a starry sky in a pool of water" "3375": "if you wanted to see the lighting distort according to the spherical shape of the normal map, would that just be part of fixing the math in the section where you sample from the env map, or is there more to it?" "3412": "What are the benefits to having 3 top-middle-bottom EnvMaps vs just using 1 EnvMap for the whole thing?" "3453": "Blackboard: Preview of how the EnvMaps will work" "3588": "I'm not sure I understand the point of the bottom map. Will the ground be contributing lighting to objects above the ground?" "3684": "Will you need a set of EnvMaps for each 'level' in Z?" "3786": "Any plans for doing over-brightening on the lights? (Or even HDR?)" "3877": "Could you contain all lighting information in a 5 byte bitmap: 0-255 Absorbance/reflectance scale for RGB, Alpha, and scattering? I want to try it but I feel really hesitant because you warned against non-32 bit aligned structs" "3950": "Even just using a 0-2 lighting range gets good results" "3976": "Do you plan on 'camera level' lighting effects such as 'stun grenade' for lack of a better example?" "4015": "If you can do without alpha, could you possibly use RGBE, where the E is the exponent for all channels?" "4111": "Is saturation very hard to overlay?" "4140": "Introduce render_entry_saturation" "4379": "Blackboard: Saturation" "4438": "Calculate the Avg and Delta" "4563": "Check it out in-game and then drive it off an animated parameter" "4686": "Will light get reflected horizontally from walls etc. in this scheme?" "4733": "Yay! Now we can oversaturate" "4748": "Close down" --- name: "day100" title: "Reflection Vectors" markers: "66": "Recap where we left off yesterday" "140": "Blackboard: Surface reflectance" "312": "Blackboard: Straight reflection model and Collision detection" "665": "Look at the code" "745": "Blackboard: Orthographic projection" "931": "Make the Z-axis our EyeVector" "951": "Blackboard: A "premature optimisation"" "1123": "Compute the bounce on the assumption that the eye vector is always [0, 0, 1]" "1278": "Compile and see what happens" "1323": "Blackboard: Fudge factor" "1462": "Blackboard: Sampling from the environment map" "1784": "Assume that the BounceDirection is always going in the direction of the map that it's trying to sample from" "1875": "Negate the BounceDirection for the Bottom map" "1985": "Start setting up SampleDirection" "2045": "Compute the offset from the fudge factor and the coefficient" "2136": "Compute tX and tY and (erroneously) clamp them" "2240": "Figure out what the UV is" "2381": "Check it out in-game and introduce some motion" "2620": "Blackboard: The way that we're encoding things" "2652": "Change that default Normal in MakeSphereNormalMap" "2701": "Take a look in-game" "2750": "Step into the debugger" "2820": "Blackboard: We still need some degree of tilt to the mirror" "2870": "It was really just Casey being kind of blunt" "2873": "Tweak the Normal" "2941": "Check out the reflective sphere in-game" "2996": "Consider investigating what's going wrong with the Top map" "3106": "Q&A" "3170": "You could try creating a normal map with a more predictable reflection, rather than a sphere" "3233": "Is the Y-axis correctly set in the normal map?" "3298": "A pyramid was suggested by a couple of people" "3360": "Blackboard: Pyramid" "3425": "Make a pyramid" "3492": "Blackboard: Figuring out a pyramid" "3545": "Set that pyramid" "3630": "Give it a shot" "3670": "Q: So it would need to be flipped on both directions?" "3686": "Q: I think the lower reflection also needs to flip the Y there because it's the incoming vector, right?" "3726": "you said you might have to make the sky texture larger than the ground so it wouldn't miss it. Could you instead sample from adjacent sky maps (assuming they're not occluded)?" "3781": "The edge attenuation is correct, given that a reflected vector right on the edge will have a smaller Y value than ones reflected from nearer the center" "3875": "Q: Would it be possible to rotate the "incoming" sampling from the environment map so that it looks like the sphere is spinning?" "3917": "Cylinders might be useful" "4106": "Are you using a left-handed coordinate system or a right-handed coordinate system?" "4134": "Would inverted versions of the normal maps be useful? (inverted sphere)" "4157": "That's disturbing" "4175": "TODO(casey): Rotate normals based on X/Y axis!" "4349": "Q: That's a wrap!" --- name: "day101" title: "The Inverse and the Transpose" markers: "46": "Recap our current situation" "105": "Start thinking about how we'll transform Normals" "231": "Blackboard: Rotating Normals (is pretty straightforward)" "301": "Blackboard: Non-uniform scaling gets a little bit hairy" "377": "Blackboard: Pretending we have the edge of a gem" "521": "Blackboard: Vectors are not all the same" "683": "Blackboard: Normals are written differently in linear algebra" "766": "Blackboard: Sometimes you have to go down a math hole" "783": "Blackboard: Constructing the P vectors" "857": "Blackboard: Matrix multiplication" "1458": "Blackboard: Transpose operation" "1579": "Blackboard: Inverse operation" "1824": "Blackboard: Gauss steps in with Gaussian Elimination" "2126": "Blackboard: Solving equations in multiple unknowns" "2193": "Blackboard: We're just entirely in the math hole" "2237": "Blackboard: You can add or multiply any two equations with equal terms for free" "2342": "Blackboard: We can regularise operations on the rows and columns of this matrix" "2389": "Blackboard: Use numbers to clearly demonstrate Gaussian Elimination" "2472": "Blackboard: This is not JZ's term" "2487": "Blackboard: You can then divide the last remaining term by whatever the target is" "2590": "Blackboard: We want to be able to multiply a matrix by something in order to produce that identity matrix" "2678": "Blackboard: The regular solution form for Gaussian Elimination" "3492": "Blackboard: Unfortunately we didn't quite get to the inverse transpose" "3746": "Q&A" "3786": "For inverting 2x2 matrices, a simple cofactor equation is quite efficient" "3806": "All of the steps in elimination can be represented as a matrix. Starting with M and multiply by all those matrices you get the identity. So those matrices multiplied together are the inverse. Multiplying them all by the identity gives you the inverse. Is that the trick you are alluding to?" "4067": "To find the inverse matrix couldn't we just rotate by the negative angle and scale by 1 over the amount that we scaled by originally?" "4652": "I remember doing this by putting the identity besides the original matrix and performing each step to each" "4884": "If you had a matrix such as int[2][2] with the example of abcd as the variables in place, couldn't you just swap a and d and make c and b negative?" "4951": "I understood none of today's episode. Would you recommend that I rewatch it, or do you think all may become clear tomorrow?" "5011": "If you write A and then I next to each other, and apply a bunch of operations, you are computing T3T2T1 A and T3T2T1 I. Because you ended up at the identity, T3T2T1A = I. So T3T2T1 = A^-1. Therefore T3T2T1 I = A^-1" "5206": "Blackboard: Look at all of this maths" "5250": "Blackboard: Setup for Day 102 and sign off" --- name: "day102" title: "Transforming Normals Properly" markers: "31": "Yesterday we had a little bit of a problem" "85": "Blackboard: Imagining the Normals for a house" "231": "Blackboard: Recap how to get the perpendicular of a vector" "320": "Blackboard: Constructing this Normal with rotation and uniform scale" "507": "Blackboard: What happens if we do non-uniform scale?" "810": "Blackboard: How can we work around this incorrect calculation?" "1061": "Open up emacs and take a look at what's currently going on in-game" "1095": "Rotate normals based on X/Y axis" "1204": "Introduce NxAxis and NyAxis" "1314": "Give our v4s the ability to assign just to xy, yz or zw" "1356": "Check it out in-game" "1370": "Moment of realisation: We can't just normalise afterwards without having touched the Z size" "1402": "Compensate for the size changes of X and Y" "1482": "Check it out in-game" "1547": "Blackboard: Explaining NzScale" "1759": "RIP Das Keyboard 4" "1811": "Consider NzScale" "1870": "Resume working on sampling from the maps correctly" "2109": "Document SampleEnvironmentMap a little" "2341": "Pass DistanceFromMapInZ to SampleEnvironmentMap" "2413": "Blackboard: Think about the weird nature of lighting in 2D games" "2514": "Flip DistanceFromMapInZ" "2543": "Ensure we're still where we were in-game and continue to verify SampleEnvironmentMap" "2717": "Blackboard: Figure out which direction Z should be sampling in the map" "2821": "Push BounceDirection.z up to the head end and negate it there" "2865": "View it in-game, try flipping it back and investigate what is happening" "3519": "Leave that as the puzzler and go to the Q&A" "3544": "Draw the sampling vector as RGB=XYZ*0.5+0.5 to visualize it" "4010": "Is the map being clipped on either the top or bottom edge? (Don't know if that makes sense.)" "4043": "Could we calculate a value for the NzScale from the Normal.x and Normal.y so that the Normal.z is unchanged after normalization?" "4313": "Only flip the BounceDirection.z when you use the top map" "4688": "Identify that we're almost puncturing through, or inverting, the map" "4833": "Maybe you can try to write code to show points on the textures from which it is doing sampling?" "4850": "How would the anomaly shift if the sphere were to move up and down instead of left and right?" "4960": "Wondering if it shouldn't maybe be " / fabs(SampleDirection.y)"?" "5164": "Show the sampling on the texture?" "5320": "The stream's over" --- name: "day103" title: "Card-like Normal Map Reflections" markers: "83": "Recap the bug" "189": "Blackboard: Sprite cards and casting directions" "604": "Take a look at the offending notion in handmade_render_group.cpp" "721": "Base DistanceFromMapInZ on HeightOfCard" "829": "Blackboard: Figuring out the height offset for the cast" "996": "Calculate ZDiff" "1121": "Turn DistanceFromMapInZ into a more sane equation" "1236": "Initialise values" "1368": "Position the EnvMaps" "1426": "Take a look in-game" "1489": "Disable the sampling debug visualisations for now and check out the reflections" "1566": "Setup EnvMaps values for testing" "1659": "Set the Origin to the middle for FixedCastY" "1713": "Set ScreenSpaceUV to 0.5f, 0.5f and investigate the warping reflections" "2100": "Alpha out the area around the sphere" "2405": "View our sphere and verify that our BounceDirection is not changing" "2441": "Consider what else may plausibly be changing" "2530": "Blackboard: Coordinate system considerations" "2579": "Set OriginY in order to pass it to ZDiff" "2646": "Turn off the sampling overdraw and darken the sphere" "2699": "Check out our stable sphere and allow it to move around again" "2794": "Q&A" "2828": "The reflection is "inverted" - the edge should be the center and vice versa" "2833": "Q: Reflection I think is backwards, at least vertically" "2873": "How long do you anticipate it will take before we get into more game-designey type topics rather than building up the engine?" "2919": "There are 12 mins left of normal stream time!" "2950": "Investigate the sphere's apparently inverted reflection" "3193": "Blackboard: Accentuating tFarMap's falloff by squaring it" "3327": "My guess is that the normals at the edges are now pointing "straight up" while the normals at the center are pointing "sideways"" "3392": "Q: Move it and then it looks wrong" "3469": "Where are the walls relative to the sphere? If it's above it as in out of the screen, then it's wrong" "3693": "Q: Reflect Casey face" "3709": "It feels like the red and blue should swap places" "3725": "Can you make the checkerboard a bit tighter? I think the problem, if any, will show up better if there are more color transitions" "3797": "Do you only want to support standing cards and lying cards, or also any other angle?" "3859": "I think part of the problem is that it might not be 'sitting' on the floor properly" "4154": "Casey is happy, considering the software renderer" "4252": "Isn't this with optimisations on?" "4317": "This is not threaded yet?" "4348": "Kill it for today and glimpse into the future" "4387": "The green dude is tough" "4527": "What about Fresnel!!!" "4605": "Wrap it up for today" --- name: "day104" title: "Switching to Y-is-up Render Targets" markers: "142": "Z is kind of up in the air" "246": "Recap where we left off last week" "413": "Take a look at handmade_render_group.h" "474": "Toggle off the normal mapping test code" "520": "Toggle on the bitmap rendering" "648": "Toggle off the yellow debug lines" "773": "Define a couple of things in handmade_render_group.h" "1058": "Reach back into our memories to the time we were working on ResizeDIBSection" "1148": "Flip the sign of Buffer->Height" "1219": "Walk through the functions in handmade_render_group.cpp" "1437": "Arrive at GetRenderEntityBasisP and change it to handle X and Y symmetrically" "1522": "Introduce TODO(casey): ZHANDLING" "1570": "Continue walking through the functions and remove any instances of Y negation" "1627": "Take a look at how Align is computed at asset loading time and introduce SetTopDownAlign" "1798": "Blackboard: Flipping the Bitmap alignment" "1875": "Write SetTopDownAlign" "1982": "Pop back over to handmade_render_group.cpp" "2026": "Check it out in-game" "2056": "Load the bitmaps bottom-up" "2178": "Check it out in-game" "2233": "Fix the jump direction" "2360": "Fix the bitmap alignments (for now)" "2509": "We are back to parity" "2586": "Take a look at the GroundBuffer sorting" "2767": "Flip the sign of ChunkOffsetY in FillGroundChunk" "2791": "On the importance of focusing on whatever it is that you're focusing on, and to know when to stop and correct things" "2907": "Casey thinks we're in good shape there" "2947": "Q&A" "3051": "Q: Has this work fixed the normal map issue or will we need to address that specifically?" "3106": "Do you think that making the Y component to be bottom-up will also help make sense of game mechanics like gravity?" "3154": "Will we be implementing a matrix/affine transform in order to handle changes to coordinate systems?" "3181": "Blackboard: Multiplying an incoming vector by a matrix" "3505": "Blackboard: The homogeneous matrix" "3700": "The mods had a lot of work to do today, just so you know" "3725": "Casey, maybe I missed it, but when will the Z ordering be done to visually correct sprites in front and behind the character?" "3761": "It's more correct to call that the "translation part". The entire upper part is affine" "3917": "When you exit the program, Visual Studio says that there are about 8 threads terminated. Is there more than one thread in Handmade Hero right now?" "4035": "Would it be possible to have the renderer set up so the world curves back as you move along the Y-axis?" "4244": "Go ahead and end" --- name: "day105" title: "Cleaning Up the Renderer API" markers: "57": "Go ahead and see where we're at" "235": "Come back here to our code" "372": "Pull functions out into handmade_render_group.h and look at them" "445": "Remove PushPiece in favour of PushBitmap" "770": "Specify that a bitmap's alignment will be directly associated with it" "936": "Massage and pass the alignment where needed" "1333": "Check it out in-game and investigate the Shadow" "1402": "Consider drilling down into PushBitmap a little more" "1483": "Figure out what's going on with our Z-positioning" "1925": "Blackboard: Hacky shadows" "2042": "Decommission EntityZC" "2175": "Continue with the Z code" "2555": "Run it and see that it looks fine" "2574": "Halve the Z-position of EntityType_Space" "2689": "Try to handle our Z in a more sane way" "2822": "Give the familiar some attention and keep going with that" "3123": "Blackboard: How the EntityBasis is conceptualised" "3234": "Only use the EntityBaseP.z for scaling" "3271": "Check it out in-game, scrutinising the jumping" "3397": "Q&A" "3458": "Why are you using AlignX and AlignY, instead of a v2 (in bitmap)?" "3608": "Shouldn't the shadow move somewhat up when he jumps (because of the angled viewport)?" "3651": "Could you make the circle reflect a bitmap like a tree if you wanted?" "3785": "Can you let the orb sample from the ground, or is that some time away?" "3989": "How much zooming will the game support?" "4015": "I keep hearing you say entity, but I take it you don't mean entity in the Entity Component System sense. Is that correct?" "4038": "You were going to add a comment to your ZFudge code to say why XY was used only, not Z to avoid skewing trees, character, etc" "4080": "I think I missed the day, but the bitmap is being texturized using a normal function (into the sphere)?" "4090": "When are we going to scale the hero down?" "4130": "Casey feels like there's a bug with our edges" "4155": "Would you implement a "lamp in a dark room" effect with shadow mapping?" "4242": "Will there be emitters of some kind, like sparks from a fire?" "4264": "How would you implement a lamp in a dark room effect in a 2D game?" "4325": "Is it common in game development to use normal function for texturizing? Is it performant? Or is it much more common to break in texturizing triangles surfaces?" "4447": "Will the entities have projected shadows or just blob shadows like the head has currently?" "4508": ""Un-optimized"? Don't you have -O2 on?" "4580": "Will the shadow be reflected in the normal map?" "4597": "Will the particles effects system interact with the normal maps?" "4650": "Go ahead and close things down for the day, then" --- name: "day106" title: "World Scaling" markers: "163": "Recap our current situation" "300": "Take a look in handmade_render_group.cpp" "358": "Render bitmaps using the DrawRectangleSlowly function" "438": "Call through the slow path?" "524": "Check it out in-game, considering how unoptimised the code is" "710": "Blackboard: Scaling" "923": "Blackboard: Intermediate buffering" "1014": "Blackboard: The stupid way" "1048": "Temporarily set the arrow keys to move the camera up and down" "1338": "Reduce the ZFudge factor" "1394": "See that the positions are being scaled, and go ahead and scale the size" "1545": "Check out the scaling in-game and note a bug with the tree popping" "1623": "Give the ground chunks a ZOffset" "1701": "Blackboard: Preventing leaning" "1736": "Do a Basis push for the GroundBuffer" "1807": "We're close, but things scale counter to each other" "1901": "Turn off the ground chunks and the debug rectangles, for now" "1958": "Take a good look at what's happening in-game" "2082": "Scale around ScreenCenter" "2172": "Moment of realisation: The EntityBasis->Offset.xy is currently incorrect" "2289": "Blackboard: How that Offset currently works" "2322": "Multiply the Offset by the ZFudge" "2375": "Check it out in-game and turn the ground chunks back on" "2487": "Show some problems with alpha fading" "2743": "Blackboard: Render buffers" "2817": "Turn off the ground buffer rendering and turn on multiple world layers" "2880": "Tweak the ZFudge" "2931": "Turn the ground buffers off entirely" "2963": "Consider the weird notion of Y-displacement for Z" "3050": "Set GlobalAlpha to 0 and try turning off that Y-displacement" "3230": "We want Z-slices" "3431": "Q&A" "3460": "Did I see that correctly, that the ground shadow jumps along with the hero?" "3497": "Slightly off topic but, can you quickly go over the concept behind MoveSpec? Why not have every entity have their own velocity/drag, etc. values instead? Just for organization?" "3546": "Is the jump a real mechanic or just for making the system robust?" "3569": "Why don't you pre-compose hero bitmaps into a single bitmap at initialization, so there would not be fussing with pushing pieces?" "3612": "When you are walking up a staircase, will the character suddenly snap back on Y when you transition to the next Z slice?" "3654": "If I'm not mistaken, with your way of Z-scaling it's going to be hard to support large (in Z) structures such as tall walls that should be aligned across different Z levels, no? Imagine a multi story house or so" "3742": "If there are going to be pits/ledges in the game, how are you going to render those?" "3767": "I wonder how the ball would work with the zoom in" "3930": "What games do the "bad" fade-out effect you mentioned?" "3973": "How will the staircase be scaled when you are moving up and down it?" "4033": "insofaras I didn't expect Casey to know of Hatoful Boyfriend" "4038": "Everybody knows Hatoful Boyfriend" "4104": "Have you seen/heard of "Hunie Pop" then?" "4144": "Q: That's a wrap?" "4175": "That is a wrap, Abner" --- name: "day107" title: "Fading Z Layers" markers: "205": "Recap where we left things off" "280": "Explain the necessity for Z-slices" "453": "Take a look at how our SimRegion stuff handles unpacking entities" "547": "Take out the ZOffset and reenable DrawRectangle" "642": "Turn off the camera snapping" "749": "Explain the concept of fixed Z-slices" "880": "Move GlobalAlpha" "992": "On separating update and render for entities" "1071": "Set the GlobalAlpha based on the GroundP" "1213": "Introduce CameraP" "1411": "Set the GlobalAlpha from CameraRelativeGroundP" "1483": "Take a look at the fade in-game" "1520": "Makes this a little more formal" "1582": "Blackboard: Specifying the visibility of levels" "1744": "Introduce Fade location markers" "1934": "Introduce Clamp01MapToRange" "2094": "Check it out in-game and correct the fade direction" "2285": "Allow us to go up another level" "2647": "What has Casey done?" "2699": "That's a bug" "2710": "Investigate what's going on" "2886": "Set the MaxEntityRadius for Z to 0.0f" "2971": "Set the SimBoundsExpansion for Z to 0.0f and then to GameState->TypicalFloorHeight" "3101": "See what that gets us" "3171": "Fix Clamp01MapToRange" "3195": "Check out the fade and get the FadeBottom working" "3381": "Check it all out and stagger the stairwell location" "3442": "Walk down the levels and note some issues to work on" "3589": "Q&A" "3616": "Why were some of the trees upside down?" "3737": "Are the head and body entities off to the side supposed to scale with the main character?" "3979": "What is Z-fighting and is it something that you have to worry about in a game like this?" "4011": "Blackboard: Z-Fighting" "4775": "Stream is over" --- name: "day108" title: "Perspective Projection" markers: "143": "Take a look at where we're at" "316": "Blackboard: Perspective projection" "588": "Blackboard: Capturing light in optics (optional)" "1234": "Blackboard: Crazy stuff we can do for photorealism, and camera hoods (optional)" "1606": "Blackboard: The approximation" "1941": "The ZFudge multiplies, but the equation for perspective projection is not a multiplication" "2023": "Implement the equation" "2704": "Take a look in-game and double-check everything" "2855": "Moment of realisation: Our offset is still happening in pixels" "2939": "Do the perspective computation in pixels and work on the values" "3600": "Blackboard: Do the maths one more time" "3847": "Q&A" "3893": "Is squinting analogous to closing a camera's aperture?" "3942": "Are you intending to multiply by XYZ and not just the XY as the variable says?" "3971": "Wasn't the room height 8 meters? That's about 3 times the height of a normal room, so you have to increase the focal length to compress everything" "4014": "Q: Expect a ton of prestream questions" "4027": "Wasn't the parameter already converted to pixels? If so then I think you are converting meters to pixels twice" "4079": "If you wanted to use this code to make a full 3D game such as a first person shooter, how much would you have to change to give the player an adjustable FOV option?" "4298": "How long do you think this is gonna take?" "4382": "No OpenGL, no audio library, no anything. How's being a masochist coming along?" "4493": "Hello! As a software developer, I understand the performance benefits of C++ are important. However, there are a lot of REPL-based code-at-runtime tools coming out that streamline development on both the web and in games. How do you feel about this departure from traditional software development tools?" "4634": "Do you use iPhone? If it's a yes, I would like to give you a copy of my game for iOS" "4654": "Will this game have cinematic mode?" "4687": "I use an iPhone... for my butt" "4709": "Would the renderer be able to support something like zooming out for one screen that is twice as large as normal?" "4883": "Lots of quick time events, too?" "4894": "Where about is the explanation of the reloading the code while running? It sounds like fun" "5017": "What kind of game is this going to be and what will the point of it be?" "5071": "When the game is finished, do you expect the game to look as good as if you made it in a commercial engine?" "5191": "Can I learn how to be a better programmer from this channel?" "5216": "Are you planning any DLC for this game?" "5268": "Do you use Windows Media Center a lot in your game dev process?" "5311": "Why does he move slower at higher zoom?" "5392": "Will the game be fun?" "5408": "Will you cover things like patching and downloading code from the internet?" "5428": "Are you planning on implementing some kind of shader support?" "5489": "Will this game have a Collector's Edition? I want a plastic dragon in it for $150" "5555": "It's dinner time" --- name: "day109" title: "Resolution-Independent Rendering" markers: "96": "Recap where we're at" "193": "Take a closer look at that perspective projection" "342": "Blackboard: The components of the perspective equation" "501": "Determine the size of our monitor" "732": "Think about MetersToPixels and resolution independence" "847": "Encode our hotspots as being proportional to the size of the bitmaps" "1128": "Get rid of MetersToPixels from the encode call" "1184": "Blackboard: We are going to specify sizes in meters" "1276": "Introduce WidthOverHeight and specify our expected sizes" "1415": "Whenever we do that read... right..." "1472": "Do this without any values in the pipeline" "1962": "Blackboard: Unit cube" "2285": "Finally do that MetersToPixels projection" "2450": "Check it out in-game" "2473": "Debug it" "2521": "Check it out and make PushBitmap start specifying the size that it thinks things should be" "2826": "Take a look at the bitmaps in GIMP" "2860": "Synthetically scale up the HeroBitmaps" "2936": "Check it out and tweak the camera values" "3096": "Clean this stuff up" "3380": "Base MetersToPixels off the ScreenDim.x" "3547": "Demonstrate this resolution-independence" "3874": "Q&A" "3938": "Should the hero/tree sizes not be dictated by the resolution of the art, i.e. to maintain constant pixel density?" "4052": "If you want your game to be full screen, how would you want to handle screens with different aspect ratios?" "4098": "Q: Baby familiars" "4140": "Tiny shadows look funny" "4215": "Q: It could be interesting to have larger trees that span multiple Z-levels. Don't know how well it would work in our style" "4238": "Will the game support scaling to arbitrary resolutions now?" "4326": "Could you explain what the #if #endif stuff is for and when/how you use it?" "4452": "Will the stairs have different artwork for the top and bottom and if so how would you make them seamless? Per step artwork each at their own height?" "4547": "Can we at least get some crappy MS paint programmer art stairs in there instead of yellow blocks?" "4555": "What happened to the cool velocity boost from stairwells?" "4580": "Towards the end when packaging, will you show us compression methods and ways to package all the assets in one file?" "4636": "Is the hero supposed to shrink on the stairs?" "4880": "Double Semicolon!" "4916": "Q: Seems we ran out of questions. Thank you for streaming, it's always a privilege! Pre-stream was painful, though" "4922": "Thank you to the moderators: garlandobloom, abnercoimbre, chronaldragon and drive137" "5038": "Look forward to the future" --- name: "day110" title: "Unprojecting Screen Boundaries" markers: "153": "Take a look at where we left off and where PixelsToMeters still happens" "257": "Make the renderer responsible for telling us what the screen dimensions are" "574": "Blackboard: Field of view in Y" "730": "Put camera parameters in render_group" "1066": "Blackboard: Figuring out RawXY distance based on the ProjectedXY" "1136": "Calculate RawXY" "1310": "Figure out what we would fill in in terms of the ProjectedXY" "1586": "Step in and see what we're getting in terms of the size" "1781": "Check it out in-game" "1824": "Keep on the march of tightening this down" "1916": "Introduce MetersToPixels on the monitor" "2249": "TODO(casey): How do we want to control our ground chunk resolution?" "2283": "Pass DrawBuffer->Width and Height to AllocateRenderGroup and take a look in-game" "2327": "Refresh the FocalLength" "2515": "Massage the code" "2638": "Take a look in-game and introduce a way to verify the computations" "2842": "Draw the ScreenBounds" "2926": "Introduce the concept of a DebugCamera" "3233": "See it in-game" "3320": "Investigate why the entities aren't moving in and out of the SimRegion based on Y" "3411": "Draw the CameraBoundsInMeters, SimBounds and SimRegion->Bounds" "3469": "'Too Many Rects' by Casey Muratori" "3513": "Take a look at it all and start to investigate why entities are not getting pulled in up to the SimRegion->Bounds" "3797": "Q&A" "3836": "Will the 'Too Many Rects' song be on the soundtrack album?" "3850": "Should the MetersToPixels value take the pixel density of the monitor into account?" "3898": "Blackboard: How we're parameterising things at the moment" "4348": "Are you sure the camera should be looking down perpendicular to the levels? Wouldn't the perspective art work out better if you said the camera was at an angle?" "4379": "Can you please toss U, V into v2?" "4425": "Q: We will know exactly how far away they are sitting if they have properly purchased their Handmade Hero branded Microsoft(r) HoloLens" "4464": "Blackboard: Non-joke important thing regarding VR headsets" "4613": "Is 'real32' ambiguous because it could be either floating point or fixed point?" "4665": "Is the non-smooth movement at higher zoom levels due to not being optimized or some sort of issue with sub-pixel smoothness?" "4686": "Would it look different if you scale WidthOfMonitor and FocalLength together, constrained to the same ratio?" "4796": "Could you put a slider for the user to change their distance to the camera at the start of the game, like some games do with gamma?" "4843": "We're about done" --- name: "day111" title: "Resolution-Independent Ground Chunks" markers: "54": "Make sure Ignored are unique names for Miblo" "137": "Pull the debug camera back a little further" "249": "Up our tree count" "272": "Start making the game very slow" "341": "Check out all the trees and forecast today's work" "550": "Look at the ground" "680": "Re-enable this GroundBuffer routine" "746": "Give PushBitmap a scale, take a look and note that the Basis isn't being cleared" "813": "Change the Basis back to the Default" "905": "#if 0 the GroundBuffer routine and add visualisation for the places where GroundChunks are being rendered" "1027": "See those places and note that it's never updating where the GroundChunks are" "1075": "Fix that update and take a walk through the world" "1168": "Figure out why we're not getting anything in the bitmap" "1296": "Get the outlines drawing in the right place" "1418": "Get FillGroundChunk working" "1619": "Give DEBUGLoadBMP the ability to let us ask for the default alignment" "1778": "Continue working on FillGroundChunk" "1875": "See if that produces anything more usable for us" "1991": "Verify that the problem is in the Bitmap" "2027": "Try and step into FillGroundChunk" "2098": "Moment of realisation: Visual Studio is too dumb to set that breakpoint when building in -O2" "2179": "Initialise Buffer->WidthOverHeight" "2262": "Look at that frame rate" "2593": "Only render ground layers that are close to the camera" "2754": "Consider optimising some of the renderer" "2960": "Q&A" "2987": "There are 15 mins left of the stream, since you went over in the prestream" "3022": "No stream tomorrow, right?" "3026": "How are you going to handle the ground chunks on the further layers which disappear while still on-screen? Will you need to expand the visibility range based on layer distance?" "3136": "Some elements in the ground are being repeated now for some reason" "3174": "I'm afraid of using sorting and stuff when making games 'cause I'm afraid that if I get too many items it will slow down. Or shall I not worry about that?" "3249": "I think it'd be cool to see really far down through, for example, floors made of glass / ice" "3304": "Will the memory footprint keep getting bigger? There's so much raw pixel data being stored right now, is this a concern at all, will we be compressing data to save ram? I imagine not, but it still feels like we're using too much memory for just a 2D game. Correct me if and because I'm wrong" "3481": "Are the ground chunks stored in some data structure (e.g. hash map or grid) or are they recalculated each frame (I was wondering, because ground chunk knows its position, but wouldn't that be implicit in its position in the data structure)?" "3519": "There was horizontal repetition of some splats but not all of them" "3556": "Do you think you are roughly 1/5 of the way through completing the game at this point?" "3664": "hen all RAM (even on GPU) is used, when the game is put into background (switching a short time to another application) all the memory has to be swapped in and out, right, even to the GPU? Or what strategy is used to prevent swapping in and out of big memory chunks?" "3745": "Q: Are we rotating and scaling the splats on the ground chunks to get the maximum variability?" "3789": "I noticed the hero's head would clip through the trees (i.e. trees on the top part of the room) on occasion and then it would fix itself. What's causing that?" "3835": "Close this down" --- name: "day112" title: "A Mental Model of CPU Performance" markers: "137": "Blackboard: Optimization" "238": "Blackboard: CPU + GPU instructions" "328": "Blackboard: Math operations done wide (SIMD)" "506": "Blackboard: An example instruction" "610": "Blackboard: Issuing an instruction is expensive" "793": "Blackboard: Optimization considerations" "956": "Blackboard: Memory access costs" "1074": "Blackboard: Cycles" "1325": "Blackboard: You should always know how many cycles you have to work with" "1477": "Blackboard: You won't always have all cycles available for use" "1557": "Blackboard: What is a cycle?" "1898": "Blackboard: Pipeline stages" "2076": "Blackboard: Why pipeline? (Doing the laundry)" "2381": "Blackboard: Latency and Throughput" "2633": "Blackboard: Where latency causes us a problem" "2913": "Blackboard: Cache miss" "3061": "Blackboard: Hyperthreading" "3162": "Blackboard: Optimization, the platform" "3307": "Blackboard: So that is optimization" "3325": "Blackboard: Efficiency" "3570": "Q&A" "3613": "Would you be willing to make more blackboard episodes? This is very informative" "3646": "Are you going to be using anything like VTune for measuring performance?" "3686": "How are instructions written in cache memory?" "3753": "Do we manually issue prefetching or is that something inferred by the CPU by looking at how we access memory?" "3908": "I know this is a long way off, but after Handmade Hero is done, do you plan to continue educational streams?" "3934": "How often do you estimate the actual amount of work prior to implementing a feature vs just implementing it and measuring it?" "4139": "So if memory takes a few hundred cycles if the instructions have to reach out to the hard drive, what impact would that have?" "4274": "Two questions: 1) Are there ever any cases where we have to worry about one of our instructions being decoded into multiple microcode instructions without our knowledge?" "4396": "2) In optimizing, have you set up the code in such a way that you can optimize things function-by-function with this eventuality in mind, or will we have to restructure some of the functions to allow them to be optimized?" "4597": "Would it be inefficient to offload the cache to an SSD over/or with minimal RAM usage or would the latency be too much?" "4652": ""Premature Optimization is the root of all evil." What's your take on that quote?" "4768": "Is there any way to use or avoid hyperthreading to your advantage?" "4784": "What do you tell someone who doesn't like emacs?" "4839": "Does hyperthreading reduce maximum bandwidth because it has to switch between states, or can both states operate at the same time?" "4880": "In your experience what drives the "good enough" optimization and how do the novice guys get a handle on that?" "5040": "Wrap things up" --- name: "day113" title: "Simple Performance Counters" markers: "124": "Blackboard: Basic process of optimization" "362": "Gather statistics" "525": "Revisit __rdtsc" "622": "GAME_UPDATE_AND_RENDER: Add __rdtsc cycle counts" "683": "Introduce debug_cycle_counter in handmade_platform.h" "832": "Support folks on platforms such as Linux and Mac, etc." "1122": "Compile, clean and run" "1184": "FillGroundChunk: Turn off the ground chunks" "1224": "Get a look at those timer values" "1569": "Run the game and see the debug cycle count" "1645": "We are already missing our budget" "1696": "Confirm what we know to be true" "1725": "RenderGroupToOutput: Add a timed block" "1795": "Introduce DebugGlobalMemory to enable us to access this timing stuff even when we shouldn't have access to it" "1930": "Note the difference between the two cycle counts" "2014": "Confirm that DrawRectangleSlowly is the culprit" "2116": "Introduce HitCount to discover if DrawRectangleSlowly is slow because it is slow, or because it's called so often" "2265": "Discover that we're calling the renderer thirteen times and DrawRectangleSlowly 64 times" "2345": "Figure out how many pixels we're filling" "2569": "Interpret the data" "2608": "Bust out some emacs-fu" "2622": "Note that we're not operating on that many more pixels than the total on the screen" "2661": "Blackboard: Overdraw" "2790": "Blackboard: Progress report" "2844": "Turn off the NormalMap" "2938": "Understanding ballpark timings" "3113": "Make an estimate" "3648": "AVX-512 hype" "3675": "Q&A" "3714": "Why no text labels on the counters?" "3730": "I'm sorry if this is something you've gone over before, but can you explain the difference between new and malloc() in C++ and when each is useful?" "3784": "Is your handwriting as bad in real life as it is with a tablet?" "3802": "Can you also cut out instructions by doing more work to save previous computations. Like d - XAxis, followed by d - XAxis - YAxis. Should that just be 2 instructions?" "3830": "Do you think we'll do multithreading in the software renderer?" "3847": "Is it possible to Quad-pump every operation?" "4049": "I meant, put it in wide instruction (SIMD)" "4142": "Would you talk Jeff into doing an optimization stream where you are the TA?" "4201": "That is the end of the stream" --- name: "day114" title: "Preparing a Function for Optimization" markers: "91": "Open things up and recap" "168": "DrawRectangleSlowly: Increase efficiency" "213": "Create DrawRectangleHopefullyQuickly" "274": "DrawRectangleHopefullyQuickly: Skip the preamble" "342": "Remove all unnecessary code" "404": "Look at what's happening" "481": "Make the edge testing code more explicit" "589": "Blackboard: See what's happening with these inner products" "724": "DrawRectangleHopefullyQuickly: Test U and V instead" "792": "Run the game" "813": "Make these U and V computations more efficient" "880": "Run the game and ensure that everything still blits fine" "916": "Continue pruning" "1082": "Flatten the routine" "1195": "Blow out v4 Blended into scalar form" "1278": "Take a close look at the routine and precompute InvTexelA" "1415": "Blow out v4 Dest and Texel into scalar form" "1530": "Flatten BilinearSample and SRGBBilinearBlend" "1682": "Assess our situation" "1735": "Unpack and optimise the Lerps" "2037": "Run the game and annotate the code" "2133": "Flatten SRGB255ToLinear1" "2198": "Flatten Unpack4x8" "2339": "That's everything flattened" "2362": "Note that the code is faster" "2458": "We have a nasty problem with the unpackings" "2641": "Blackboard: What is our "wide" strategy?" "2923": "Set the stage for SIMD" "3045": "Consider solidifying texture boundaries" "3113": "Leave it for today" "3189": "Q&A" "3208": "The way the code is written now you have a very long dependency chain (between instructions). Will you break down the code to remove it?" "3402": "Why did you write float instead of real32 this stream?" "3434": "Why use -O2 instead of -O3 or -Ofast (possibly with -fverbose-asm)?" "3486": "Do you ever use exclusive or operations to avoid pipeline stalls? If not, what do you use?" "3544": "Aren't those square roots pretty expensive?" "3811": "Will you make multiple SIMD backends? (SSE?/AVX/FMA versions)" "3844": "You could loft some of those variables out one more loop" "3898": "How expensive is the float<>int conversion compared to the rest of the workload?" "3940": "Since xAxis and yAxis are usually perpendicular, should we special case for that? In the same vein, should we special-case for axis-aligned?" "4016": "Does the compiler do any automatic SSE optimization (or have option for it?)" "4141": "sqrt_ss vs sqrt_ps vs sqrt_pd?" "4316": "Would SSE allow doing sRGB using exponent 2.2 instead of approximating using one of 2, without a huge performance hit?" "4361": "The main reason why you don't get automatic SIMD is precise exceptions. You probably need to tell the compiler that you don't need them" "4484": "What happens if "/arch:AVX2" switch is enabled?" "4526": "Look at this AVX-512 stuff" "4611": "FMA is fused multiply add" "4728": "Yeah, looks like different caps bits" "4763": "Wrap things up" --- name: "day115" title: "SIMD Basics" markers: "59": "Open us up and see where we're at in terms of performance" "112": "Blackboard: SIMD on x64" "394": "Blackboard: How do we use SIMD?" "496": "Blackboard: CPU vs GPU framebuffers" "850": "Blackboard: "SOA" vs "AOS"" "1102": "Blackboard: How this stuff actually works" "1333": "Blackboard: Strided loading on NEON" "1522": "build.bat: Turn off compiler optimisations" "1546": "Internet: Intel Intrinsics Guide" "1734": "handmade_render_group.cpp: Initialise some __m128 registers and use some SIMD intrinsics to operate on them 4-wide" "1867": "Debugger: Go to disassembly and look at the SIMD registers" "2162": "handmade_render_group.cpp: Set four different values in the registers" "2196": "Debugger: See those different values in the registers and note the order in which they are loaded" "2387": "handmade_render_group.cpp: Turn Square functions into multiplies" "2464": "Fix the loop to work on pixels in batches of 4" "2780": "Run the game and note that we are overwriting our boundary" "2835": "handmade_render_group.cpp: Temporarily clip the buffers" "2899": "Separate the memory loading stuff from the computations" "3058": "Declare the arrays before the loop" "3440": "Debugger: Run and investigate the error" "3498": "handmade_render_group.cpp: Correctly test ShouldFill[I]" "3530": "Run and note that we're (almost) back to where we started" "3582": "handmade_render_group.cpp: Walk through the routine" "3713": "Load in the Pixels from the right place" "3753": "Run, note that we're back to some semblance of good, and glimpse into the future" "3846": "Q&A" "3870": "Would it be faster to unpack pixels using a union of an int32 with a struct of 4 int8's, instead of doing 4 shifts and masks per pixel?" "3915": "Why don't we go: Y<2 and X<2 and go through in blocks, instead of a line?" "4064": "Is it better if we calculate if the pixel should be filled and queue it up and only do the calculations once we hit 4 of them?" "4245": "Casey was using a Das Keyboard 4, but it broke, so he is currently using an unknown keyboard he had lying around" "4290": "Sorry, maybe this is off-topic: Would it be correct to say anyone coding in Java, by default, is not making use of any of the SIMD stuff, or do you think the JIT compiler is smart enough to make use of it in certain circumstances, maybe with some analysis of the bytecode?" "4349": "How often do you optimize for cache misses vs optimizing with SIMD? I got the impression that cache misses are by far the most important things to look out for" "4480": "Please send my best regards to Jeff" "4492": "Schedule-wise, how many more weeks until you are done with optimization of the renderer?" "4501": "Will you be covering Morton order texture swizzling?" "4614": "Possibly a noob Q: Have you ever run into problems with floating point arithmetic, and what are some good approaches to avoiding those problems?" "4897": "starchypancakes [...] Casey said SSE2 was standard, I guess I'll start there" "5046": "Is there a way to track how memory gets stored to cache?" "5281": "Off-topic: Do you know if JAI will have extensions / a method for using SIMD?" "5330": "How much do you need to think about the intrinsic instructions while programming, or does the compiler usually take care of that? Is this the big difference between using GNU and Intel compiler, for example?" "5437": "I think he's essentially asking how proficient compilers are at automatically emitting SIMD instructions" "5634": "Do you have to take the instruction cache into account? Or is it large enough?" "5679": "How does intrinsics and parallel processing work together? Does each CPU have registers to do intrinsics? If so, could we increase X-fold the number of pixel rendering in our code if we computed in parallel?" "5733": "Wrap things up" --- name: "day116" title: "Converting Math Operations to SIMD" markers: "83": "Recap yesterday's work" "166": "build.bat: Switch to -O2" "262": "Think about doing the TestPixel TIMED_BLOCK over a wider range" "320": "handmade_render_group.cpp: Move the timer around the for loops" "350": "Debugger: See that there are two loops that are more or less the same" "386": "handmade_platform.h: Number these DebugCycleCounters" "409": "handmade_render_group.cpp: Rename TestPixel to ProcessPixel and remove TIMED_BLOCK around DrawRectangleSlowly" "455": "Debugger: Look at the DEBUG CYCLE COUNTS" "492": "handmade_render_group.cpp: Introduce END_TIMED_BLOCK_COUNTED" "576": "Debugger: See that the ProcessPixel count is now more accurate [243cy/h]" "634": "handmade_render_group.cpp: Write this in SIMD" "995": "Run and see that it's still producing the correct result" "1007": "build.bat: Switch to -Od" "1047": "Debugger: Inspect TexelAr" "1288": "handmade_render_group.cpp: Continue transforming these Texel computations into SIMD" "1761": "Run and note that we're running just fine [575cy/h]" "1786": "handmade_render_group.cpp: Continue making these wide" "2234": "Compile and see if we made any mistakes [557cy/h]" "2251": "handmade_render_group.cpp: Do the rest of this wide, except for the Clamp" "2439": "Intel Intrinsics Guide: _mm_sqrt_ps" "2471": "handmade_render_group.cpp: Do _mm_sqrt_ps and continue converting to SIMD" "2619": "Run and note that we are blitting correctly [427cy/h]" "2634": "Debugger: Look at what Clamp01 does" "2837": "Intel Intrinsics Guide: _mm_min_ps and _mm_max_ps" "2925": "handmade_render_group.cpp: Do the Clamps wide [179cy/h]" "3002": "Run and note that the game is already running faster" "3047": "Reflect on the straightforwardness of this work" "3114": "Consider what's left to convert to SIMD" "3166": "handmade_render_group.cpp: Do PixelP wide" "3256": "Run and note how fast it's running [124cy/h]" "3378": "Debugger: Investigate what the compiler is doing with those 50 cycles" "3774": "handmade_render_group.cpp: Finish doing the SIMD here" "4052": "Run and note that we're creeping forwards [121cy/h]" "4086": "Recap and glimpse into the future of doing the Loads and Repack in SIMD" "4268": "Q&A" "4292": "How do you cover multiple CPU technologies intrinsic-wise? Preprocessor switches on dedicated intrinsics for each? Also, whom to read on ASM? I'm thinking Mike Abrash?" "4389": "We have come from 385 cycles to 123. Does something like the 80%-20% rule apply? Do you think we will get down to 50 cycles?" "4522": "The way we use mmSquare, does it calculate the argument twice?" "4541": "Debugger: Determine if the compiler is doing common subexpression elimination for these multiplies" "4871": "Deep, concentrated investigation" "5154": "Look at how fast the game's running" "5179": "Where do OpenCL and other GPGPU frameworks fit into optimization? It seems like if something is SIMD-able, it could just be done wider on a GPU. Are there workloads that are better suited to the CPU and SIMD?" "5346": "We have optimizations still on?" "5359": "Why are there optimizing options in the compiler if one will end up typing SIMD functions?" "5461": "Do you know of the _mm_setr_ps intrinsic (and _pd etc) - note the r in setr? It loads the values in reverse order, i.e. in the order that is more intuitive" "5498": "When do you think we will thread the renderer?" "5517": "Possibly misguided question, is there a way to overload operators to use SIMD instructions instead?" "5565": "Is padding and alignment still something you have to concern yourself with? I remember doing SIMD in the mid 2000s, and SIMD was essentially worthless (much of the time) if your data wasn't aligned" "5623": "Addendum: By "concern yourself", I mean, is it something the compiler now handles more autonomously when you "engage" SIMD" "5655": "Will you generate asm for NEON (if you port to arm of course)? GCC seems to be pretty bad at generating correct code with intrinsics (from my experience on Android)" "5703": "How would you know if doing something will speed up the code? Especially when it's a fairly large change to the codebase and when time is limited, I find myself reluctant to perform such optimizations in fear of introducing bugs" "5806": "What do you think you'll next want to convert to SIMD, in case I want to practise over the weekend?" "5932": "Can you compile it -Od and show how SIMD has helped there?" "5972": "Would it be a good exercise (albeit a large one) to study a simple CPU and write some soft for it? Arduino or something ancient? I wanted to learn coding for GBA for a while" "6064": "Let's rephrase: what CPU would you advise to study that would be simple enough yet representative enough of the general stuff you should know about when working with CPUs?" "6172": "How long have you been working on this and when do you think you will finish?" "6209": "re you going to optimize gameplay code as well?" "6225": "Have you heard of the JayStation2 Project from Jaymin Kessler, working with the Raspberry Pi 2 B+?" "6243": "Close things down with a recap of the week's optimisation work" "6483": "Shout out to the mods" --- name: "day117" title: "Packing Pixels for the Framebuffer" markers: "125": "Load up the code and consider optimisation" "249": "handmade_render_group.cpp: Comment out if(ShouldFill[I])" "334": "Blackboard: Interleaving four SIMD values" "867": "Blackboard: Establishing the order we need" "946": "handmade_render_group.cpp: Write the SIMD register names that we want to end up with" "989": "Internet: Intel Intrinsics Guide" "1043": "Blackboard: __mm_unpackhi_epi32 and __mm_unpacklo_epi32" "1144": "Blackboard: Using these operations to generate what we need" "1457": "handmade_render_group.cpp: Name the registers in register order" "1515": "Internet: Double-check the parameter order of the unpack operations" "1582": "handmade_render_group.cpp: Start to populate the registers" "1612": "Internet: Keeping in mind how often you move between __m128 and __m128i" "1719": "handmade_render_group.cpp: Cast the Blended values from float to int" "1787": "Use structured art to enable us to see what's happening" "2087": "Debugger: Watch how our art gets shuffled" "2320": "handmade_render_group.cpp: Produce the rest of the pixel values we need" "2503": "Convert 32-bit floating point values to 8-bit integers" "2647": "// TODO(casey): Set the rounding to something known" "2708": "Blackboard: Using 8-bits of these 32-bit registers" "2852": "handmade_render_group.cpp: Bitwise OR and Shift these values" "3027": "Blackboard: How the shift operations work" "3164": "handmade_render_group.cpp: Implement these shifts" "3306": "Debugger: Take a look at the Out value" "3453": "handmade_render_group.cpp: Break out the values" "3502": "Debugger: Inspect these values" "3515": "handmade_render_group.cpp: Fix the test case" "3572": "Debugger: Inspect our stuff" "3613": "handmade_render_group.cpp: Write Out to Pixel" "3668": "Debugger: Crash and reload" "3703": "Debugger: Note that we are writing unaligned" "3862": "Blackboard: Alignment" "3954": "handmade_render_group.cpp: Issue _mm_storeu_si128 to cause the compiler to use the (unaligned) mov instruction" "4043": "Recap and glimpse into the future" "4110": "Q&A" "4199": "Will the operations be reordered to reduce the number of ops and load / stores?" "4321": "You are calculating Out like or(or(or(r, g), b), a). Would it be better to do it like this: or(or(r, g), or(b, a)), so first two or's are not dependent on each other?" "4497": "handmade_render_group.cpp: Write it the way mmozeiko suggests" "4651": "Do you need to start with 32-bit floats? Is there further optimization that doesn't need the casting?" "4701": "Blackboard: Multiplying floats vs Multiplying integers" "4794": "Same for texture bilinear adds together" "4803": "handmade_render_group.cpp: Implement mmozeiko's suggestion" "4980": "Can you compile /O2 to compare it to last week's performance?" "4996": "Why did you make macros for your SIMD operations (mmSquare, etc.) vs making functions?" "5019": "Are these intrinsics the same on other operating systems or compilers, as long as it's using Intel architecture?" "5080": "Why do you say unaligned store is nasty? As far as I know, for latest Intel CPUs (at least starting from Ivy Bridge) unaligned load / store is not very expensive anymore (<5% difference)" "5185": "Is scalar access to __m128 elements still slow on Intel?" "5238": "The processor window is 192 instructions" "5281": "I don't understand how one optimizes by using the intrinsic or function" "5331": "_mm_cvttps_epi32 always truncates. Would that be better than messing with rounding mode?" "5445": "handmade_render_group.cpp: Switch to _mm_cvttps_epi32" "5570": "Wrap up" --- name: "day118" title: "Wide Unpacking and Masking" markers: "25": "Overview of optimization work" "90": "Recap where we were yesterday" "110": "Current issue: Black bars" "200": "Blackboard: Writing correct values to destination" "335": "It's ok to do all operations for all pixels" "412": "Blackboard: Another option: Combine old/new values" "494": "Blackboard: Build a mask" "540": "Masking out the invalid new values" "650": "Making sure we save the original destination" "698": "Haven't SIMD-ized the load yet, deal with OriginalDest differently" "775": "Problem with WriteMask: Haven't computed it yet!" "840": "Use cheesy set macros to set WriteMask" "856": "Handmade Hero: A Bit Garish edition" "920": "Fixing the 'problem': Mi macro for uint setting" "960": "Another thing: Fabian's rounding mode comment" "1017": "Some work to do with the last for(I) loop" "1174": "The explicit version of unrolling the loop" "1320": "Checking we're still working: under 100 cycles now" "1390": "Doing the destination the same way" "1430": "Just saved more cycles moving things out" "1475": "Fixing the WriteMask nonsense" "1538": "SSE Comparison Operations" "1580": "Blackboard: Comparisons for wide operations" "1783": "Using comparisons to generate WriteMask directly" "1910": "Working WriteMask with wide operations" "1930": "Problem: can't get rid of if entirely..." "1960": "Solution: Clamp U and V" "2020": "Get rid of the if entirely!" "2034": "Handmade Hero: Uniformly Stretchy Edition" "2045": "Fixing the bug: U/V copypasta typo" "2105": "Doing the texel fetch wide as well" "2250": "Not optimizing yet, just translating to SIMD" "2385": "Adjusting the texture fetch to use the wide values" "2430": "Converting the fetch coord by truncating" "2520": "Getting fX and fY by subtraction" "2610": "All correct, under 70 cycles" "2650": "No longer need to initialize the Texel values" "2760": "Everything in SIMD now but texel loads" "2810": "Blackboard: Unpacking the color data" "2910": "Pulling out colors using masks and shifting" "3200": "Blackboard: The matrix of sample reads" "3300": "Packing the sample data into 4-wide registers" "3348": "Some crazy emacs macro kung-fu" "3410": "Doing the Texels the same way as Dest" "3485": "Working texel read, and...almost 50cy/pixel" "3565": "What if there's nothing in the mask?" "3679": "Q&A" "3723": "Could you not just align the X coord to a 4-pixel boundary up front, and thereby use aligned loads and stores?" "3783": "Are you pulling this code over into ground splats soon?" "3915": "Is it me or after this whole SIMD conversion the cycles per pixel are much more consistent?" "3944": "I have kind of missed the past few days, I'm wondering if doing CPU intrinsics exclusively for SSE2 in your game code is bad or are we targetting SSE2? For example, should we wrap everything into platform-specific files so its easier to target other platforms?" "4115": "What does it mean for intrinsics that don't have a specified throughput?" "4131": "Instead of loading the destination first would it be faster to skip that and instead do a masked write e.g. _mm_maskmoveu_si128" "4316": "Would it be a good idea to just use SIMD for all our math operations in all our programs?" "4536": "Example of an intrinsic with no throughput: _mm_cmpgt_ps" "4860": "Agner Fog says the throughput is 1" "4936": "[What is latency vs throughput?]" "4966": "What is the end goal of the optimization, trying to get below a certain threshold, or just to get everything converted?" "5034": "Does size of variables and stuff matter to SIMD, like 32bit vs 64bit?" "5145": "Is the SSE code doing any cache prefetch or hinting stuff yet?" "5232": "Couldn't we use a half-float instead of floats as we don't need that much precision with only 255 discrete values?" "5330": "Is the normal map code going to be converted to SIMD?" "5367": "End of the stream" --- name: "day119" title: "Counting Intrinsics" markers: "10": "Lesson: Das keyboards are horrible" "96": "Recap of last episode and today's agenda" "153": "Prep work for getting pre-optimization vs post-optimization cycle counts" "223": "Add cycle counting to DrawRectangleSlowly" "281": "... 350 vs 50 cycles per pixel!" "317": "How long *should* it take to fill each pixel? Let's count up all the intrinsics and their throughputs..." "430": "... How can we automate this counting process?" "478": "Answer: Override the intrinsics with macros that add to some counter variables" "527": "Oops, there's still some SIMDizing left to do here..." "570": "Use _mm_add_ps to increment PixelPx by 4 instead of scalar adds (2-3 cycles better)" "715": "dx and dy can be baked into PixelPx and PixelPy (2 cycles better)" "788": "Should we loft PixelPx and PixelPy axis multiply/add calculation out of the inner loop?" "839": "Maybe loft just the multiplies but not the add? Hmm..." "860": "... try lofting the multiplications. (1-2 cycles worse)" "950": "Note: Texture fetches can't be done in SIMD" "1012": "Fabian on why _mm_maskmoveu_si128 is so slow. Don't use it! It bypasses the cache." "1095": "Adding a #define for each intrinsic to count operations (_mm_add_ps, _mm_mul_ps, etc)" "1305": "Start setting up the intrinsic #defines to count operations" "1425": "Preprocessor cleverness that handles the fact that intrinsics often take other intrinsics as params" "1654": "Define load/store to nothing" "1719": "Mini-rant about the compiler not doing instruction/intrinsic instrumentation automatically" "1906": "We've got counts!" "1935": "Double check that counts make sense" "2007": "Multiply counts by throughputs to get total latency estimate" "2127": "_mm_castps_si128 latency is difficult to know." "2152": "looking up the processor core type in windows" "2212": "_mm_and_ps and bitwise ops are 1/3 cycle on Nehalem" "2428": "Use a macro to sum up the latency*counts to get a rough throughput total" "2575": "Well, Isn't that fancy: Measured throughput is lower than the theoretical best throughput. Instructions are likely executing on multiple ALUs per cycle" "2740": "How many units are in Nehalem core?" "2897": "... Two?" "2952": "On the limitations of executing multiple instructions per clock" "3085": "We're quite close to the max theoretical throughput." "3139": "Memory latency probably isn't hurting performance" "3167": "Make an #if toggle for the intrinsic measurement code" "3238": "How much is gamma (sqrt) costing us?" "3390": "A troubling visual artifact appears around our hero..." "3467": "Aha! An issue with the linear/SRGB code" "3628": "gamma is costing only 6 cycles" "3665": "This is a reasonably optimized pixel loop" "3692": "Agenda for next session: Optimize outside/around the pixel loop." "3716": "Q&A" "3729": "Is this what you were looking for?" "3796": "Nehalem diagram: Only one FPU?" "3952": "Worth timing the load/stores with no ALU ops to see how much we're memory bound?" "4366": "You counted _mm_and_ps wrong." "4415": "Are you doing pre-multipled alpha? (Yes)" "4418": "Could you run the game with task manager open?" "4577": "Will this game only work for your specific processor?" "4603": " Are you going to update the yellow background textures?" "4652": "The texture fetch should be an L1 cache fetch." "4690": "In an alternate universe where nobody cares for art, do you think optimization would still be a focus for developers?" "4774": "Any idea why my cores get maxed out when running Handmade Hero with the XCB platform layer?" "4833": "Why wasn't there a greater speed increase after removing gamma correction?" "4962": "How will we split up the drawing onto multiple cores?" "4976": "What's the floating head?" "4994": "Question about _mm_ps_sqrt and common subexpression elimination" "5054": "What's that drum-like background noise?" "5077": "Do you see all the questions?" "5107": "Can rdtsc be inaccurate with CPUs that vary their cycle rate?" "5183": "How does the CPU do things ahead of time if things are supposed to be done in order?" "5374": "Do you expect a 16x speedup from multi-threading?" "5399": "How do you select the instruction set for optimizing?" "5575": "Aren't the Unity hardware survey results pretty different than the Steam ones?" "5641": "What are the gains you get by writing your own software renderer vs using SDL, GPUs, etc?" "5724": "Can a processor work through different types of calculations in a single cycle?" "5836": "What kinds of things can be delegated to the GPU?" --- name: "day120" title: "Measuring Port Usage with IACA" markers: "31": "Review of last session: cycle counting code" "80": "Fabian: Instruction counts including throughput numbers is not accurate, does not properly take into account CPU's ability to overlap different ops" "240": "Accurate way is to write tool to simulate the CPU, as Casey did for the XB360" "270": "... or Intel architecture code analyzer (IACA)" "455": "Overview on how to use IACA with the code" "488": "Marking sections with IACA_START and IACA_END" "560": "Modifying build.bat to include the iaca directory" "609": "For linux/unix compatibility, mind your case when including files" "698": "Running the IACA command line" "790": "Reading the IACA results" "928": "Trying to decipher the meanings of the letters in the IACA table" "1018": "IACA can output graphs?" "1032": "IACA reports max throughput of 86.60 cycles" "1076": "There maybe some more room for optimization..." "1110": "IACA is pretty nice!" "1160": "Adding some macros to turn IACA on/off" "1187": "Thanks to Fabian for the suggestion" "1244": "Fabian: bilinear and squaring don't need floating point" "1279": "Move the sRGB->linear conversion after the bilinear" "1405": "Bake normalization into color" "1525": "Works fine (not much improvement)" "1672": "Remove a number of multiply ops by keeping things in 0-255 space (no improvement)" "2207": "Diff IACA output from the run with the removed multiplies and the one prior" "2490": "Getting rid of 43 instructions did not improve throughput reported by IACA" "2566": "Seems to be doing the same number of multiplies either way" "2589": "Compiler was smart enough to do the transformations?" "2707": "What other optimizations could we do?" "2839": "Use _mm_mul_mulhi_epi16 to do the square operations more wide prior to the FP conversion?" "2974": "Blackboard: Mask out A and G, which leaves R and B aligned to the 16-bit SIMD boundaries" "3173": "Blackboard: _mm_mullo_epi16 vs. _mm_mulhi_epi16" "3276": "problem: this will square our alpha as well" "3319": "We'll have to use another instruction to handle alpha" "3420": "Bitshifting / masking to pull the components from their 16-bit lanes" "3519": "Wrong result! It's Q&A, but let's try to debug first..." "3995": "Issue found: Should be masking 16-bit, not 8-bit" "4020": "Better, but still a strange result" "4077": "How to avoid squaring the alpha?" "4158": "Just pull the alpha out prior to the squaring?" "4186": ".. that works fine" "4210": "Now let's convert everything to use the 16-bit squaring" "4259": "... around 6 cycles improvement, but small visual problem with the bilinear" "4297": "Found the issue: We were reading only from SampleA" "4307": "Bilinear looks better, but still oddity with green fringing around the hero" "4336": "Found the issue, looks good, but..." "4362": "... we're actually 8 cycles worse now" "4394": "Why? Let's run it through IACA" "4424": "Throughput bottleneck: Inter-iteration? Good question for Fabian" "4439": "Total number of micro-ops have gotten smaller - 350 vs 306 vs. 283 but throughput is worse" "4556": "Could use the same technique when loading the destination, but probably not a good idea" "4621": "Q&A" "4650": "CP stands for Critical path" "4693": "IACA was showing Port 1 as the bottleneck, so reducing multplies won't help" "4745": "Inter-iteration means that run x of the loop depends on the prior run" "4796": "Try hoisting out the TexturePitch/TextureMemory (several cycles improvement)" "5034": "How do you support AVX? What about register saving through context switches?" "5107": "Replace sqrt with mul/rsqrt?" "5474": "Some comments on port 1 pressure from Fabian" "5659": "How can removing the sqrt help if it's done on the multiply port, not the adder port?" --- name: "day121" title: "Rendering in Tiles (Marathon)" markers: "96": "Reintroducing the Intel Architecture Code Analyzer" "646": "A long time ago, in RAD's source tree" "780": "blowtard, an analytical tool for the Xbox 360's PowerPC Tri-Core Xenon written by Casey" "1324": "How IACA's output differs from Casey's stats in blowtard" "1856": "Looking at how to get our cycle count down" "1941": "Manually unroll the Fetch / Sample loop" "2190": "Group by Sample" "2247": "Use _mm_setr_ps as suggested by Fabian a long time ago" "2534": "Taking a look at the total throughput count" "2598": "Casey needs some more soya [sic] milk" "2657": "Could we do a load once, and grab out the two values that we needed?" "2748": "Day 121 Blackboard: Explanation of possible texel loading optimisation" "3032": "Figuring out how the compiler is loading the texel data" "3618": "This is fine, then" "3661": "We multiply by TexturePitch and sizeof(uint32) four-wide manually, which is stupid" "3726": "Shift up FetchX_4x by 2, rather than multiply by sizeof(uint32)" "3820": "Premultiply FetchY_4x by TexturePitch_4x" "3847": "Give the compiler the wide stuff so that it can see it as wide" "4281": "_mm_mul_epi32 does not do integer * integer" "4423": "Port pressure (we're back to InterIteration)" "4666": "Blackboard: Hyperthreading" "5242": "Blackboard: Designing how to break up the renderer for multithreading to ease pressure on the caches" "5542": "Blackboard: Divide the frame buffer into chunks that are sized appropriately for the cache" "5995": "Blackboard: The plan for setting up the renderer" "6047": "Implementation of interleaved scanlines, in readiness for hyperthreading" "6396": "Blackboard: The logic of interleaved scanlines" "6757": "Updating compiler directives for folks who use LLVM" "6920": "Implementation of frame buffer divisions, in readiness for multi-core processing" "7530": "Go to Disassembly of DrawRectangleSlowly in order to diagnose bogus cycle count" "7804": "Frame buffer divisions, continued" "8450": "Introduce GetClampedRectArea" "8532": "Problematic thing: Our convention for rectangles before was that they did not include their final value" "8853": "Fix the cycle counter for DrawRectangleSlowly again" "8982": "A shortcut didn't work out. (!quote 297 + !quote 298)" "9056": "Loft FillRect above the loop" "9394": "Introduce PixelPxRow in order to keep PixelPx as a wide value rather than having to set it each time" "9590": "Check IACA for performance difference and revert to setting PixelPx each time through the loop" "9808": "Shuffle calculations around to figure out how the performance is affected, for good or ill" "10277": "Blackboard: Thinking about that alignment problem" "10558": "Align MinX and MaxX" "10818": "Microsoft Visual Studio 2013 has stopped working" "10923": "Dancing trees" "10983": "Change our loads and stores to no longer be unaligned" "11045": "Assess performance difference and revert back to the unaligned load and store instructions" "11112": "Make sure that we actually always fill the real clip region and not write outside the clip region" "11230": "Blackboard: Our options for filling the pixels" "11352": "Implementation of alignment to the ending edge" "11808": "Clip the leading edge" "11981": "Blackboard: ClipMask" "12093": "Try setting StartupClipMask by using _mm_srli_si128" "12148": "// TODO(casey): This is stupid." "12370": "Early-out the FillRect tests" "12601": "Start passing ClipRect through to DrawRectangleQuickly" "12935": "Moment of realisation, with introduction of the InvertedInfinityRectangle" "13068": "Temporarily adjust ClipRect in order to avoid a crash" "13164": "Introduce TiledRenderGroupToOutput outside of the timer" "13437": "Update DrawRectangle to take the clipping information" "13638": "Update DrawRectangle{,Quickly} to use the Even / Odd information" "13760": "Break the screen up into pieces and render them separately" "14074": "Stretch your legs, Casey" "14188": "We can finally end the stream" "14227": "Q&A" "14232": "a) your top and right clip is off-by-1!" "14394": "_mm_mullo_epi32 is SSE4 intrinsic" "14697": "Will you revert yesterday changes where you changed bilinear pixel unpacking code from float mul to int mul? It was faster with float mul." "14724": "How many more marathon streams will we have? I thoroughly enjoyed the 4+ hours today." "14747": "You should give a big thanks to Rygorous for sticking around and trying to give you tips knowing full well that you wouldn't see them in chat" "14767": "would it be better to have tile sizes always divisible by 4 horizontally (or even 16 to be cache aligned), then there will be no need to deal with alignment and masking?" "14827": "(clip) one too few pixels. look at the edge of the screen." "14960": "just pretty sure I saw glitchiness/off-by-1-pixel stuff near the edges but it might've been the video encoding" "15068": "(tile size %4) - not masking for textures, but ClipMask variable" "15210": "Q: holy crap. our 1st marathon." "15230": "Time for Casey to go to bed, with closing remarks" --- name: "day122" title: "Introduction to Multithreading" markers: "170": "Blackboard: Multithreading" "215": "Blackboard: CPU state" "308": "Blackboard: How the OS conceptualises this" "415": "Blackboard: Threads" "504": "Blackboard: Fibers" "578": "Blackboard: Why do we care about this?" "730": "Blackboard: "Core"" "856": "Blackboard: "Hyperthread"" "1096": "Blackboard: The OS comes in and switches" "1180": "Blackboard: Logical cores" "1353": "Blackboard: "Out of order" vs "In order"" "1448": "Blackboard: The OS and "interrupts"" "1679": "Blackboard: "Preemption"" "1817": "Blackboard: What we have to do on Handmade Hero" "1931": "Run Handmade Hero and monitor its CPU usage" "2081": "Switch to DrawRectangleSlowly" "2231": "Blackboard: Why not do faster single-threaded processing?" "2447": "Set the stage to create some threads" "2607": "win32_handmade.cpp: Introduce CreateThread" "2969": "Run the code and exit" "3015": "Temporarily create lots of threads" "3046": "Solidify things" "3194": "What happens on exit" "3447": "Hype up building without CRT" "3516": "The compiler doesn't know about threading" "3603": "Q&A" "3627": "What does closing the handle of a thread do for you when you release the handle to the OS? Does it open up resources and increase performance?" "3692": "Doesn't increasing the number of threads to match the hyperthreads count increase cross-core/cross-context switches, thus making it less efficient for small operations?" "3801": "Is there any advantage to creating a separate process to render the graphics in the context of game development?" "3898": "Is it still a while yet before we look at other platform layers than win32?" "3931": "Why just 15 threads? Why not future proof?" "3979": "Will we be querying the system for its CPU count to determine how many threads to use?" "3988": "Do you have control over on which core the thread executes from the program itself (thread affinity)?" "4077": "Do you plan to make path-finding multithreaded?" "4105": "Q: Jonathan Blow had created 10,000 threads on his compiler demo. Some people wondered how in the world that could happen" "4193": "No one will ever need more than 16 threads" "4205": "Nobody will ever need more than 256 colors. Ever. - the GIF committee" "4251": "Not related, but why do you use C over C++? Is it just personal preference?" "4331": "Okay. Can we stay on stream after you end the episode's recording for another try on the story?" "4340": "I'll email you the story, meanwhile, here's two other questions: 1) Which programmers' code would you recommend reading? Let's list Sean Barrett's public github (as well as streams from time to time) to start the list" "4368": "2) When are we covering patching / couple of words on brief basics? I assume it mostly has to deal with asset updates and updates of code that handles them?" "4460": "What was the reason for dismissing the use of fibers early on?" "4498": "Have you made any progress on the licence text for ports to other programming languages?" "4570": "Would it be possible for you to boost the sound of your voice on stream? I've always found that it is barely high enough even with all mixers at maximum volume possible" "4599": "Wrap things up" --- name: "day123" title: "Interlocked Operations" markers: "153": "Blackboard: Thread Synchronization / Communication" "211": "Blackboard: Processes" "248": "Blackboard: Threads" "322": "Blackboard: Problem #1 - Knowing what work to do" "425": "Blackboard: Problem #2 - Sync / When work is done / visible" "675": "Blackboard: Conceptualising how threads work" "754": "Blackboard: Doing a busy-wait loop" "979": "Blackboard: Preventing multiple threads from doing the same work" "1137": "Blackboard: x64 provides special instructions" "1186": "Blackboard: "locked exchange"" "1440": "Blackboard: "interlocked compare exchange"" "1611": "Put on the Pig Hat" "1723": "Blackboard: Being slyfox with the other primitives" "1802": "Blackboard: "reads and writes" in a multithreaded context" "1916": "Blackboard: cache lines" "2374": "Take off the Pig Hat and open the code" "2417": "win32_handmade.cpp: Make four threads that do different work" "2561": "Run Handmade Hero" "2577": "Make the threads look for work to do" "2931": "Run and inspect the debug output" "3017": "Moment of realisation: You need to let ThreadInfo values persist" "3098": "Inspect the output" "3152": "Explain what's happening" "3290": "The writes to EntryCount are not in order" "3424": "The reads are not in order" "3494": "Q&A" "3520": "Is your use of "for (;;)" instead of "while(1)" a stylistic choice or is there a benefit / drawback I'm missing?" "3617": "What's the problem with not being interlocked and seeing the same value, as your "TODO" suggests?" "3759": "Blackboard: Why two threads did the same work" "3929": "Do mutexes that I've seen used for multithreaded code in other places rely on those interlocking instructions, or are they something completely different?" "3983": "What is your opinion on lockless queues?" "4098": "What's the point of an infinite loop to begin with? It ends at some point, doesn't it?" "4126": "What threading libraries do you recommend and why (e.g. boost or pthreads)?" "4177": "What's better: a job scheduler from where each thread can get a job, or separate queues for each thread?" "4245": "Blackboard: "Single producer / Single consumer" vs "Single producer / Multiple consumer"" "4479": "I think that the point of "lockless" is that it doesn't use an operating system-level lock" "4495": "Blackboard: "lock free"" "4606": "Hey Casey, an InterlockedIncrement is a lock-free operation! (The terminology is shitty. The original term is "non-blocking" which is more useful)" "4660": "Is it reasonable to synchronize the receiving of network packets on one synchronized thread?" "4756": "Later in the development cycle, will you go over threading for other operating systems like Mac and Linux?" "4785": "What are the advantages of having a queue of jobs, instead of creating a thread every time you add a job?" "4804": "Blackboard: Overlap vs Performance" "5090": "Recap and glimpse into the future" "5288": "Close things down" --- name: "day124" title: "Memory Barriers and Semaphores" markers: "35": "Recap/Review" "165": "Yesterday's TODOs" "240": "TODO 1: Ordering of writes" "393": "CompletePastWritesBeforeFutureWrites" "622": "Looking up memory fences" "730": "Venturing into Visual Studio's include folder" "800": "Putting in an actual CPU barrier" "872": "Where do we go from here?" "900": "Volatile introduction" "1123": "TODO 2: Interlocked writes" "1210": "Looking up InterlockedIncrement" "1297": "TODO 3: Already taken care of by volatile" "1314": "TODO 4: Ordering of reads" "1404": "Checking our work" "1460": "NB: Don't use all 16 hyperthreads!" "1545": "Job completion" "1720": "Waiting for all the threads to complete" "1850": "Suspending and resuming threads" "2091": "Semaphores" "2248": "WaitForSingleObject for suspending" "2435": "Creating the semaphore" "2664": "Problem: Threads never wake up!" "2810": "Waking up by releasing the semaphore" "3207": "How we'll use the semaphore" "3266": "Testing the semaphore" "3410": "Work for tomorrow" "3433": "Q&A" "3504": "In the visual studio output window you can right click and deselect some of the stuff" "3536": "Why does this have to be so complicated??" "3577": "Why did you put the memory barrier in a macro when it's platform-specific code?" "3607": "After the sleep, some threads still pushed several strings, leaving out some of the other threads" "3656": "Would Sleep(0) in your spin-lock help anything?" "3755": "IMGUI has been trending. Sorry if you get asked this more than you like to." "3787": "When you initially started this project, what were the first 5 things you coded and why?" "3802": "I missed most of tonight, what does the volatile keyword mean?" "3827": "How do you plan to maintain cache line coherency between processors? Can physical CPUs share a cache line?" "3903": "Blackboard: MESI and Cache Coherency" "4455": "Was volatile added in C99?" "4477": "Wait, so transactional memory wants to simplify concurrent programming by allowing a chunk of load/store instructions to execute in atomically. Have you messed with this?" "4505": "Blackboard: Transactional Memory" "4738": "Transactional memory is often advocated as an easier-to-use replacement for locks that avoids any possibility of a deadlock, so I wanted your thoughts." "4864": "Why are we building a generic work distribution when the tiled renderer is designed to cleanly split up the work anyway?" "4965": "Wrapping things up" --- name: "day125" title: "Abstracting the Work Queue" markers: "7": "We are absolute control freaks here, people" "85": "Recap and set the stage for today" "226": "win32_handmade.cpp: Introduce DoWorkerWork" "343": "Let our normal thread do work" "415": "Run and see what the threads are doing" "457": "Follow the compression oriented programming approach" "550": "handmade_render_group.cpp: Figure out a way to do TiledRenderGroupToOutput on multiple threads" "638": "handmade_platform.h: Consider pulling in work_queue_entry" "714": "win32_handmade.cpp: Rewrite PushString as AddWorkQueueEntry" "918": "Note the necessity of _mm_sfence" "973": "Pull work_queue_entry down into the test code" "1038": "Split DoWorkerWork in two" "1234": "Think" "1278": "Put while(EntryCount != EntryCompletionCount) into QueueWorkStillInProgress" "1369": "Rename and finish writing these functions" "1848": "Compile and run and see what the threads are doing" "1874": "Discuss our options" "2071": "Rename GetNextWorkQueueEntry to CompleteAndGetNextWorkQueueEntry and make it take work_queue_entry Completed" "2129": "Rearrange ThreadProc slightly" "2244": "Massage DoWorkerWork" "2271": "Tweak the QueueWorkStillInProgress loop" "2335": "Compile and consider removing one more call" "2412": "Go for it and make the work_queue two separate things" "2662": "Run this again" "2719": "handmade_platform.h: Hoist these functions in" "2761": "Think about this a little bit more" "2831": "handmade_render_group.cpp: Write the usage code first" "3006": "Compile and express hate for const" "3040": "Finish writing TiledRenderGroupToOutput" "3298": "Compile and run and crash" "3322": "Moment of realisation: Gotta increment by the correct value" "3332": "Recap and glimpse into the multithreaded future" "3369": "Q&A" "3455": "Will you start new threads for every queue that you make?" "3569": "Still don't understand the use of volatile and memory barrier" "3593": "Blackboard: Memory and Code Fences" "4066": "Can Entry.IsValid be removed and replaced with a test to see if Entry.Data != NULL?" "4084": "What is your take on Naughty Dog's approach using fibers (+ manual management) and thread affinity to core instead of using classic worker / job approach for multithreaded gameplay?" "4103": "The work queue will take any function to do it multithreaded? Does the function need to be special so that this will work?" "4133": "Please write a lock free queue, even though I don't know what those are and if you used one" "4173": "How many CPU cycles does spawning a thread cost? Or better: what's the minimum amount of cycles to work in 2 threads to gain speed?" "4245": "I don't understand why you call it a queue if it is done potentially simultaneously" "4306": "Wasn't there already a bit of thread-related code in the win32 file?" "4324": "Will you add a cool graph over time that shows what task (e.g. from which subsystem) each thread is working on at each moment?" "4459": "Is false sharing between the entries in the work queue potentially problematic (from a performance standpoint)?" "4474": "Does volatile clear the assembly registers by pushing them into the stack and then restore by popping?" "4496": "Why would you want a compiler fence and not a process fence, and vice versa?" "4541": "Shouldn't _mm_fence() imply a compiler fence? Surely there's no point otherwise..." "4604": "Have you implemented friction?" "4614": "So, thread management is a bit like memory management (in that you want to set it up ahead of time rather than allocating them on-demand)" "4677": "The code to ask how many threads will be done simultaneously by the processor is to be added?" "4715": "Is it possible that a work queue entry spawn another work queue entry?" "4766": "(Not an expert at all, which was part of why I asked the question) False sharing causes the processor to skip the cache when different threads access stuff on the same cache line" "4901": "Actually, I can think of one use case for a compiler fence without a memory fence: writing to CPU special registers like control registers or MSRs" "4954": "Getting back into C/C++ coding after many years. Don't know why you are mixing C-style structs and C++ structs?" "4972": "Close things down" --- name: "day126" title: "Circular FIFO Work Queue" markers: "25": "Owl of Shame: Single producer/Multiple consumer issue" "213": "InterlockedCompareExchange" "260": "Fixing our shame" "379": "Siumplifying more with the API change" "540": "Implementing the multithreading API" "762": "Piping the work queue through" "873": "Global defines for AddEntry and CompleteAllWork" "960": "Typedefs for the work queue types" "1110": "Smoothing out the multithreading API" "1450": "Getting compiling again" "1680": "Initializing pointers on game startup" "1717": "Continuing clean-up" "1980": "GetCurrentThreadID for our test code" "2086": "Reviewing/Checking for bugs" "2153": "Problem: Queue never resets" "2160": "Temporary Fix: Reset queue when all work is done" "2344": "Turning the queue into a circular buffer" "2570": "Blackboard: Circular FIFO" "2655": "Implementing the FIFO queue" "3035": "Testing the FIFO queue" "3066": "Debugging the FIFO wrapping" "3350": "Fixing the completion goal code" "3540": "Working multithreaded rendering!" "3743": "Q&A" "3778": "Since the workloads don't complete in order what if one workload takes very long while the other threads wrap around in the queue such that a new workload overwrites the slot with the one that is still running?" "3866": "Now that we're multithreaded, could we compile in debug mode and have the game run at a reasonable framerate?" "4107": "Can we tell how much faster it is now that it's multithreaded?" "4324": "60 FPS test" "4383": "Instead of asserting that the queue doesn't overflow when adding an entry would it be better to just wait for an entry to be read if there's no space to write" "4405": "Would you call this a thread pool?" "4424": "When stepping through multithreaded code all the other threads stop as well, I take it?" "4510": "Can you make the number of threads an in-game configuration option?" "4533": "How long until the renderer is sorted?" "4570": "Is the WeShouldSleep still right after you changed the if condition?" "4675": "Why do you use #if 0 instead of // or /*?" "4749": "Can you show 4k?" "4787": "gasto5 Q: Is multithreaded code less reliable than singlethreaded code?" "4837": "So is the circular buffer recycling threads after they're done processing a tile? I wasn't clear on why a circular buffer was chosen." "4856": "Power cord bumped, computer shut down" "5060": "(once more) So is the circular buffer recycling threads after they're done processing a tile? I wasn't clear on why a circular buffer was chosen." "5075": "Blackboard: Circular buffers" "5193": "I just saw where you're sleeping threads if there's no work, are you still using semaphores to block and wake up threads or are you sleeping threads?" "5235": "Is the archive going to save this correctly?" "5261": "Would it be easier to implement the queue as a linked list so it has no maximum size? Since we never need to traverse the list it should still be fast." "5336": "In the rolling buffer you check each entry to be filled before writing a new one in and otherwise skip to the next slot?" "5379": "Done for the day." --- name: "day127" title: "Aligning Rendering Memory" markers: "83": "Set the stage for this week" "171": "Demo the problem with the tile size" "244": "Confirm that _mm_sfence is unnecessary" "346": "Blackboard: "Write-Combining Memory"" "823": "Blackboard: Tiles and Alignment" "1262": "Suggest rounding TileWidth and TileHeight to the nearest 4 and aligning the tiles to the 4-byte boundary" "1295": "Think some more, and then unthink it" "1331": "handmade_render_group.cpp: Ensure that we always get aligned tiles" "1407": "Blackboard: Calculating and filling the correct number of 4-pixel units" "1570": "Blackboard: The destination buffer must always allow us to overwrite it by a certain amount" "1789": "Assert that OutputTarget->Memory is aligned to 16-bytes" "1905": "Round TileWidth up to the nearest 4" "1993": "See what numbers we're getting" "2054": "Ensure that FinalTileWidth accounts for the fact that it'll be smaller" "2094": "Remove FinalTileWidth and limit ClipRect.MaxX to the OutputTarget->Width" "2123": "Remove the ClipRect adjustments" "2177": "Run single-threaded for the moment" "2226": "Moment of realisation: We're only clipping to the end, but don't handle clipping at the beginning" "2254": "Blackboard: The clipping problem" "2518": "Align the MinX and MaxX" "2828": "Blackboard: Setting the EndClipMasks" "2904": "Figure out when to use the EndClipMask" "3001": "Compile and see what's happening" "3030": "Reverse the sense of the test and run it again" "3055": "See if we're always aligned" "3076": "Compile in -O2 and turn on multi-threading to ensure everything's still kosher" "3122": "win32_handmade.cpp: Double-check that the platform code is allocating the memory aligned" "3200": "Align Buffer->Pitch to 16-bytes" "3250": "handmade_platform.h: Introduce Align16" "3313": "Everything looks fine at 1920x1080" "3373": "handmade.cpp: Setup the PlatformAddEntry and PlatformCompleteAllWork at the beginning" "3480": "Q&A" "3523": "The bitmap memory size calculation squares BytesPerPixel which allocates more memory than necessary" "3530": "win32_handmade.cpp: Remove the multiplication by BytesPerPixel" "3559": "Can you test if weird resolutions actually are working?" "3633": "handmade_render_group.cpp: Ensure that it goes all the way to the end if this is the last tile" "4026": "handmade.cpp: Hard-set the game's DrawBuffer dimensions to test our support of arbitrary resolutions" "4108": "Will you check for Cache Aliasing? With this much alignment hitting cache aliasing is much easier" "4131": "Cache Associativity aliasing..." "4167": "What about the extra pixel around the edges to deal with bilinear filtering? Will you get rid of that?" "4233": "Compile with that #if 0'd out and glimpse into the future of 4K art" "4310": "Will you keep the rendering of the two lines on separate hyperthreads?" "4413": "So this game is going to be a 4K Zelda 1-style game?" "4483": "Assess our progress and glimpse into the future of tightening up the renderer" "4598": "Shut things down here" --- name: "day128" title: "Push-time Transforms" markers: "73": "Opening things up" "158": "Blackboard: Aligning to cache lines" "601": "Renderer TODOs" "789": "Today's work: loose ends" "969": "Taking a look at coordinate systems" "1027": "Revisiting the basis transform" "1200": "Splitting up the update/render" "1362": "Doing the basis transform on demand" "1773": "Getting rid of the EntityBasis" "2124": "Initializing the transform" "2393": "Translating the calls" "2991": "Finishing up code changes" "3225": "Testing the changes" "3287": "Making render transforms work in debug" "3385": "Musings on the engine so far" "3471": "Q&A" "3545": "Everything works the first time because you think out loud." "3591": "Does the yellow part represent the loaded bitmaps?" "3740": "What does it mean to invalidate cache?" "3750": "Blackboard: Cache invalidation" "4137": "Could you summarize what you did tonight? Found it a little hard to follow along." "4258": "Could you explain what is meant when one says something is done serially?" "4393": "I missed a bit of the stream after you removed scale. Didn't you use that for scaling by Z?" "4466": "What's happening between staircase passing in the bitmaps? Is it simple scaling based on the Z axis?" "4713": "How many FPS is this running at?" "4763": "To make the 3D appearance of the staircase, would you have to make render technique to draw the walls of the staircase to start from the bottom floor and end at the top floor?" "4781": "When do you consider consulting other programmers? Where is the threshold?" "4832": "What happens if you want to apply different transforms or lighting to different parts of a scene?" "4874": "What do you expect will be the boost using OpenGL/D3D for blitting?" "4911": "Is there a concept of local space / model space / camera space / clip space in the renderer that is analgous to the kinds of translations in OpenGL/D3D that you would want?" "4995": "Unrelated to the stream, I found a video where you explain quaternion double cover, but there is no explanation of quaternions. Would you consider doing on in the near future?" "5060": "Finishing it up" --- name: "day129" title: "Adding Orthographic Projection" markers: "63": "Recap and set the stage for today" "112": "handmade.cpp: Turn off the debug lines" "192": "Blackboard: Why ground tiles are no longer seamless now that we're doing perspective transforms" "403": "Blackboard: Doing the displacement with perspective transform" "473": "Take a look at how FillGroundChunk is working" "718": "Propose addressing GroundBuffers in terms of coordinates that mean something in the real world" "791": "Walk through FillGroundChunk" "882": "Consider telling the renderer to use the perspective transform" "1004": "Start by writing an API call to the renderer to enable seamless ground tiles using orthographic transform" "1159": "Provide the ability to switch between perspective and orthographic" "1320": "handmade_render_group.cpp: Write Perspective function" "1431": "Write Orthographic function" "1542": "Consider how to allow Perspective and Orthographic to flow through the pipeline" "1583": "Force them to be rectilinear" "1674": "Clean up and compile before moving on" "1728": "handmade.cpp: Make the orthographic version work" "1771": "handmade_render_group.cpp: Write at orthographic path in entity_basis_p_result" "1939": "handmade_render_group.h: Introduce bool32 Orthographic" "2069": "Take a look in-game" "2089": "handmade_render_group.cpp: Walk through entity_basis_p_result" "2134": "Correct OriginalP to P" "2162": "handmade.cpp: Consider what PushBitmap is doing in FillGroundChunk" "2268": "handmade_render_group.cpp: Ensure that MetersToPixels is being calculated correctly" "2308": "Debugger: Step in and see what's happening in Orthographic" "2502": "Moment of realisation: The Scale cannot be 1.0f" "2562": "Debugger: Step into FillGroundChunk" "2694": "Are we doing PixelsToMeters and MetersToPixels backwards?" "2778": "handmade.cpp: Correct the Pixels / Meters calculation in Orthographic" "2800": "Take a look in-game" "2897": "handmade.cpp: Walk through FillGroundChunk" "2952": "Make it splat in a more concentrated area and turn back on the debug lines" "3028": "Splat about half the space and note that there doesn't appear to be 100 things in that tile" "3043": "Return to splatting the whole tile and tweak the sizes" "3119": "Take a look at the seams" "3170": "Create a checkerboard pattern to accentuate the seams" "3287": "See the seams" "3345": "build.bat: Switch to -O2 and run around the world" "3384": "Q&A" "3438": "When do we make everything hardware accelerated to get the amazing powers of ROTATION?" "3476": "handmade_render_group.cpp: Demo rotation" "3647": "Will we see how to find "expensive" functions that are called between frames? So far we SIMD only the pixel renderer right now, because we know" "3715": "I'm so sorry, Casey-sama" "3780": "Can you briefly go over the rest of what we're going to do to the engine before we start implementing gameplay code?" "3862": "This will all be very game-codey" "3952": "Right now to get more performance out of the render you multithread it to render the screen in chunks. GPUs are parallel by design so how do these two concepts differ?" "3988": "Blackboard: Tiled vs Non-tiled GPUs" "4200": "If there are no better questions, wouldn't the solution to internally link objects in an arbitrary amount of linked lists be performance problematic? Or is there a smart solution I am missing here?" "4243": "I feel like the GroundChunks move faster than the trees on the same plane" "4264": "The gaming industry is too hard to enter. Why do potential programmers waste their time?" "4292": "There's a lot of mug action going on. Are you one of those coffee-blooded programmers?" "4306": "I am about to commence studying a degree in Computer Science. I love gaming, and the concept of creating them is fairly interesting, though I am not entirely mathematically inclined. This being the case, would you suggest I stay away from Game Development and steer toward my original plan of Software Engineering?" "4352": "I have Ruby and JS background and I was wondering if you normally do unit testing / behavioral testing in game development, or is it just too hard because of visual elements?" "4421": "On your site you responded to the question, "Why are you doing this project?" with: "Game programmers need to start creating high-quality teaching materials for their trade." How much progress have you made towards developing the twitch VODs into high-quality teaching materials?" "4464": "Do we know how many ms per frame we have right now for the game logic? So far we push 60 FPS but it's hard-locked and maybe we already have some room for game logic?" "4520": "Will everything be programatically animated or will it be done by an artist? Or both?" "4531": "Do you have a YouTube channel?" "4553": "Can you show a snippet where you implemented a hash table?" "4643": "If Vulkan is out by the time you hardware accelerate the renderer, would it be possible to use Vulkan?" "4662": "Why do you think Microsoft decided to omit the 1080i resolution option for the XBox One? Do you think it was too difficult for them to include?" "4678": "Do you plan on commenting the code before releasing the engine?" "4764": "It's just insane that we can have so many laggy games today when CPUs / GPUs are that fast... Thank you for bringing some light into the reasons for that (bad programming and/or languages)" "4979": "Is unsafe memory key for high-performance optimizations needed for modern-day games? I've heard this is the key reason memory-safe languages like Rust and Haskell won't be able to take over for extremely low-latency applications or drivers, but I don't know enough about the domain" "5141": "Shut things down" --- name: "day130" title: "Seamless Bilinear Tiling" markers: "20": "Recap" "108": "Where we left off" "220": "Isolating the bug" "420": "Checking for chunk abutting" "550": "Formalizing the texture boundaries" "625": "Blackboard: Bilinear filtering for things in tiles" "1052": "Fixing the texture sample" "1098": "Blackboard: Thinking through the sample" "1512": "Biasing the sample location" "1710": "Checking the sample bias" "1885": "Ground chunk aprons" "1999": "Blackboard: confirming the apron math" "2056": "Accounting for the apron" "2250": "Work to do on the ground chunks" "2402": "Putting back the debug camera" "2580": "Filling ground chunks multithreaded" "2582": "Adding a low priority queue" "3120": "Problem: ground chunks need to be aligned" "3245": "Adding the ground chunk work to the queue" "3405": "Abort mission, not enough time" "3444": "Crash due to alignment problems" "3600": "Q&A" "3650": "Good stream today. Sometimes it goes really great" "3681": "The Ground Chunks render differently every time you go upstairs and come back down. Are you planning on fixing that before Z-sorting?" "3728": "Can you address the recurring question: "This stream isn't about making games?" I'm tired of trying to explain what this stream is about" "3925": "How long have you worked on this project?" "3961": "How are you deciding what gets queued or not, and high vs low?" "3980": "How are you going to implement seamless tiles with what Yangtian Li creates?" "4017": "I don't see any object oriented patterns. Are you using object orientation?" "4028": "I assume the Yellow/Cyan/Magenta squares are for debugging. What do they represent?" "4126": "You always say "we", who is "we"?" "4163": "You say "3 work weeks" but do you feel like you could maintain this pace 8 hours a day?" "4251": "It seems like the ground chunks are only getting generated when they would actually be visible, not before. When you get the ground chunk into the low priority queue, will empty ground be visible for 1 or 2 frames while they are being generated?" "4297": "Do you think at the end / near end, someone like Jon Blow would be interested in making a game with the Handmade Hero engine in a similar format to see how the game design phase evolves the engine? I know at Pixar they get new and interesting results with unplanned collaboration between artist and engineer" "4342": "Wrap things up" --- name: "day131" title: "Asynchronous Ground Chunk Composition" markers: "160": "Run the game and identify our slight problem" "262": "Why we couldn't generate the ground chunks on a separate thread" "407": "handmade.h: Allow PushSize_ to take an Alignment" "495": "Introduce AlignmentMask" "613": "Blackboard: Turning a power of 2 into a mask" "783": "Set the AlignmentOffset based on the AlignmentMask" "1007": "Go over PushSize_ one more time" "1077": "Debugger: Step through PushSize_" "1128": "handmade.h: Add ## __VA__ARGS to these Push* definitions" "1258": "handmade.cpp: Pass 16 to this PushSize call and run the game" "1317": "Consider queueing up all of FillGroundChunk" "1396": "Turn off TiledRenderGroupToOutput" "1420": "handmade_render_group.cpp: Switch to the player's camera and walk around" "1452": "On leaving part of what we're doing synchronous" "1548": "Provide a temporary storage area to enable the background task to work without the data getting overwritten" "1631": "handmade.h: Introduce GroundChunkArenas" "1735": "Introduce task_with_memory" "1798": "handmade.cpp: Create a bunch of Tasks which each create a SubArena" "1907": "Look at how FillGroundChunk works" "1948": "handmade.h: Make it implicit in task_with_memory that the memory is temporary" "1988": "handmade.cpp: Implement BeginTaskWithMemory and EndTaskWithMemory" "2050": "Do FillGroundChunk if BeginTaskWithMemory is true" "2161": "Write BeginTaskWithMemory" "2328": "Put TiledRenderGroupToOutput on the background threads" "2413": "handmade_render_group.cpp: Introduce RenderGroupToOutput as a non-tiled version" "2541": "handmade.cpp: Call RenderGroupToOutput" "2667": "handmade_intrinsics.h: #define CompletePreviousWritesBeforeFutureWrites" "2720": "handmade.cpp: Clean up" "2751": "Do AllocateRenderGroup from &Task->Arena" "2815": "Introduce fill_ground_chunk_work" "2871": "Put fill_ground_chunk_work into PLATFORM_WORK_QUEUE_CALLBACK" "2910": "Put fill_ground_chunk_work into FillGroundChunk and fill it out at the end" "2954": "Call PlatformAddEntry" "2994": "handmade.h: Implement GetArenaSizeRemaining" "3098": "Introduce GetAlignmentOffset" "3177": "Calculate that Result in GetArenaSizeRemaining and clean up" "3265": "handmade.cpp: Cast GetArenaSizeRemaining to uint32 in FillGroundChunk" "3372": "handmade.h: Implement SubArena" "3521": "Walk through our new functionality" "3600": "Debugger: Start stepping through the code" "3892": "Debugger: NextInHash is not valid" "3952": "handmade.h: Put the += Size in the correct spot in PushSize_" "3986": "Debugger: Identify that MaxPushBufferSize needs to take PushStruct into account" "4007": "handmade_render_group.cpp: Conditionally set MaxPushBufferSize in AllocateRenderGroup" "4080": "Debugger: Continue stepping through and note that the TempCount is 2" "4118": "handmade.cpp: Set Task->BeingUsed = true in BeginTaskWithMemory" "4132": "Run the game successfully" "4172": "handmade_render_group.cpp: Reenable the debug camera" "4273": "Q&A" "4322": "If one of the task_with_memory, which has several task_with_memory in front of it, calls EndTaskWithMemory first, will the stuff in front of it be screwed up? Or is this case not possible? Because I have a feeling that I don't understand something" "4348": "Blackboard: What goes in the arenas and how they work" "4489": "We already had memory reserved for the GroundBuffers. Why couldn't we just use that memory for the threaded stuff?" "4570": "What are the lines on the screen?" "4618": "win32_handmade.cpp: Set OffsetX and OffsetY to 0 in Win32DisplayBufferInWindow for now" "4769": "So you've basically constructed a task pool for ground chunks to run on another thread. Can you use this mechanism for other types of tasks as well?" "4789": "Why not put the stuff at the top of the transient arena (i.e. ground chunk bitmaps) into the permanent storage?" "4809": "Why does it flash magenta once in a while? Is it because we're drawing without the work being finished?" "4840": "Wrap things up" --- name: "day132" title: "Asset Streaming" markers: "86": "Recap" "115": "Hidden stall: Asset loading" "275": "Considerations for asset loading" "433": "Types of assets" "720": "Moving out assets into a single place" "850": "Breaking up asset types" "940": "Problems: data must be available, direct reference" "1048": "Pulling out static bitmaps with IDs" "1340": "Stopgap for other asset types" "1423": "Extending PushBitmap to take an ID" "1825": "Removing a failure case" "1993": "Allocating space for the bitmaps" "2410": "Deferred asset loading" "2495": "Loading one asset at a time" "2972": "Loading assets on demand" "3022": "Background loading assets" "3262": "Anticipate mr4thdimention's editor 4coder" "3511": "Cleaning up" "3614": "We background-load now" "3661": "Q&A" "3680": "Is it useful when assets can be modified from outside (file on disk overwrite, maybe even in memory) and still work in-game? Is it now supported after an asset is loaded, as I could not see any callback to check if a file is modified, as your glazing speed refactoring was way too fast for me?" "3770": "In load_asset_work, where is the memory for the filenames stored?" "3870": "What are the trade-offs to give him more power forcing render pushes out of the rendering queue order?" "3883": "You said we got asset streaming done in an hour, but do we need to do multiple passes on it? If so, why?" "3964": "Where you check if an asset is already loaded or not, if an asset would take a very long time to load, would it check if it's loaded again to try to load the asset again? Not sure if that makes sense" "4089": "Do you consider terrain an asset too so that it can stream?" "4112": "Why: "if (Task) { work }" versus "if (!Task) return; work"?" "4179": "What are the trade-offs to give him (the rendering queue) more power forcing render pushes out of the rendering queue order when it is multi-threaded so the rendering can be controlled more fine-tuned? You where thinking about that in the stream" "4311": "How much of the DirectX / OpenGL typical pipeline are you pre-emptively designing in to your code now?" "4368": "What do you think about Microsoft's _vectorcall as a calling convention for speed?" "4504": "Is it possible for the OS to lose track of memory that you ask for?" "4559": "Could you elaborate on OpenGL and DirectX death?" "4657": "What would be a good way to expand asset streaming to support increasing level of details? (What I'm thinking of is loading a smaller version of the asset first and then the bigger size resources)" "4764": "I recently started from the beginning of the series (on 13 atm). Do you suggest watching all of the Q&As or just going episode -> episode?" "4838": "How infuriating is it to deal with massive asset pipelines dealing with dozens of pieces of software on a large AAA project?" "4968": "Call it a day" --- name: "day133" title: "Preliminary Asset Structuring" markers: "157": "Recap and set the stage" "319": "Blackboard: "One in, One out"" "466": "Blackboard: Only load once!" "556": "Outline our tasks for the day" "605": "handmade.cpp: Get TopDownAlignY back in" "739": "Run the game to see the correct alignment" "747": "handmade.h: Make things only load once" "845": "handmade.cpp: Check to see if the asset in question is loaded" "974": "handmade_intrinsics.h: Introduce AtomicCompareExchangeUInt32" "1145": "Compile and run" "1181": "FillGroundChunk will render incorrectly if the bitmap to be composited doesn't exist" "1302": "handmade.cpp: Only mark the ground chunk as having been filled once we know it has been" "1339": "handmade_render_group.cpp: Introduce AllBitmapsValid (AllResourcesPresent)" "1430": "Add MissingResourceCount to render_group" "1471": "Problem: With ground chunks being rendered on a separate thread, they could potentially be evicted at the wrong time" "1549": "Possible solutions to this problem" "1689": "handmade_render_group.cpp: Introduce CleanupRenderGroup" "1812": "handmade_render_group.h: Add game_asset_id to render_entry_bitmap" "1887": "handmade_render_group.cpp: Introduce UnlockAsset in CleanupRenderGroup" "1939": "Introduce LockAsset in PushBitmap" "1989": "Assess this locking implementation and undo it" "2226": "handmade.h: Introduce AssetState_Locked in asset_state" "2286": "Add asset_state FinalState to load_asset_work" "2343": "handmade.cpp: Assess what DEBUGLoadBMP is doing and consider what to do next" "2532": "handmade.h: Expand the notion of game_asset_id to be more generic" "2595": "Introduce asset_bitmap_info" "2664": "Introduce asset_tag" "2708": "Talk about creating a table of assets which provides semantic information to the code" "2782": "handmade.cpp: Discuss how this semantic information could be used by the world generation code" "2889": "Assets: Take a look at the art assets" "2946": "handmade.cpp: Introduce PickBest to rank assets according to the given criteria" "3219": "Explain how PickBest could work" "3350": "handmade.h: Introduce asset_group" "3410": "Get it compiling and leave it for now" "3440": "Q&A" "3458": "In PickBest, would you want other types of falloffs when computing the difference?" "3477": "When compiling for 64bit, shouldn't you be using _InterlockedCompareExchange64?" "3509": "In your example of having 32 GB of assets uncompressed and 2 GB of space for them, are there techniques you can use to tell whether you will need more than 2 GB at one time?" "3584": "Can you summarize what you've done from the artist's perspective? Did you add a (light) obligation to the contract between the programmer and the artist?" "3662": "If you can't evict locked resources, what would be the point of streaming them over just loading them up front, and doesn't it put a restraint on the diversity of the environments you can have?" "3762": "Shouldn't you fill Work completely before calling PlatformAddEntry for LoadAssetWork?" "3803": "handmade.cpp: Move PlatformAddEntry after the switch statements in LoadAsset" "3846": "I may have missed this, but do you have the ability to set a hard limit on memory usage yet, e.g. so you know you can support lower memory machines?" "3889": "In a prior episode you implemented bilinear filtering. Are you going to take it a step further and implement mipmapping and trilinear filtering?" "4012": "Will the assets loaded in from a file be stored and evicted in the same way as the ground chunks?" "4038": "Song: 'Are There Questions?' by Casey Muratori" "4070": "Why only .bmp?" "4144": "The eviction stuff you're doing, is it basically garbage collection?" "4240": "Will we be using AMD hair physics?" "4327": "If you turn a bitmap black and white by altering the pixel, then would you have two copies of the bitmap? Would you delete one if you have two?" "4462": "Why do people care so much about garbage collection?" "4469": "Why use a pack-file instead of bmps? What makes it "better"?" "4581": "Earlier someone asked why reimplement virtual memory on top of the OS's virtual memory. Are we doing this just so we can have "more" virtual space?" "4665": "Are the ground chunks going to be pre-composited when using the GPU?" "4682": "Is there a reason why you split the character into three bitmaps?" "4692": "Is the rendering going to be eventually done on the GPU?" "4745": "Are game saves going to be part of that asset pack-file, or their own pack-file?" "4823": "Song: 'Q's & A's' by Casey Muratori" "4839": "Does porting the rendering to be done on the GPU mean you have to write a renderer completely separate to the CPU one, or is most of the groundwork done by having the CPU renderer done?" "4944": "I thought you hated both DRM and cloud-based stuff (based off of Jeff and Casey Show)" "5040": "Go get some ramen" --- name: "day134" title: "Mapping Assets to Bitmaps" markers: "30": "Recap" "110": "Review of PickBest" "354": "Looking at how tags might be set up" "530": "Structuring assets more generally" "1123": "Creation of handmade_asset.h" "1384": "Creation of handmade_asset.cpp, writing AllocateGameAssets" "1538": "Cleaning up compile errors" "1613": "Splitting LoadAsset" "1828": "Resuming compile error cleanup" "1855": "Moving DEBUGLoadBMP to the asset system" "2095": "Converting between assets and bitmaps" "2240": "Setting up stopgap bitmap loading" "2386": "Nuking thread_context and moving out ReadEntireFile ptrs" "2715": "Fixing the bugs that got through compile" "2762": "Loading bitmaps using type info" "3260": "Debugging missing trees" "3305": "There's a Count and a range" "3611": "Q&A" "3646": "You won't be using any formal database for the game, correct? Why?" "3869": "Is there any way I can download these episodes to watch on the go?" "3948": "Why code is C as opposed to Java?" "3973": "ssets include compressed sprite sheets, audio, video and bone rigs?" "4043": "handmade.h: Make it incumbent upon the game to set IsInitialized" "4309": "How on earth do you procedurally generate character movement?" "4403": "Can you run cloc.exe again?" "4459": "Have you ever used Unity3D? If so, would you recommend it?" "4464": "What advice do you have for relatively new programmers who are trying to ditch the OOP mindset and move onto things like Data Oriented Design and Compression Oriented Design?" "4956": "Wrap things up" --- name: "day135" title: "Typed Asset Arrays" markers: "140": "Recap the creation of handmade_asset.cpp" "275": "handmade_asset.cpp: Make the arrayed assets go through the asset system" "331": "Provide a stable way to define AlignX and TopDownAlignY with the bitmaps" "550": "handmade_asset.cpp: Remove superfluous asset types" "617": "Debugger: Read out the alignments for the bitmaps" "650": "handmade_asset.cpp: Replace AlignX and TopDownAlignY with AlignPercentage for each asset type" "728": "Remove this DEBUGLoadBMP call and edit an earlier DEBUGLoadBMP call to take into account these changes to AlignPercentage" "766": "Get rid of TopDownAlign" "807": "Run the game" "830": "Consider our current options for cleaning this up while we still don't have a pack file" "905": "handmade_asset.h: Change the structure of asset_bitmap_info" "1006": "handmade_asset.cpp: Allocate a ton of bitmaps for testing purposes" "1033": "Introduce DEBUGAddBitmapInfo" "1179": "Create assets dynamically in AllocateGameAssets" "1367": "Pull out BeginAssetType, AddBitmapAsset and EndAssetType into functions" "1547": "handmade.h: TODO(casey): Optional "clear" parameter!!!!" "1570": "handmade_asset.cpp: Continue writing these functions" "1785": "Debugger: Step through these functions" "2025": "Run the game" "2039": "handmade_asset.cpp: Get the Grass, Tuft and Stone bitmaps using this new system" "2093": "handmade.cpp: Introduce id-based picking of assets" "2193": "handmade_asset.cpp: Introduce RandomAssetFrom" "2298": "Run the game" "2358": "Debugger: See what the asset tables look like" "2397": "handmade_asset.cpp: Add the first asset in RandomAssetFrom" "2453": "Run the game and note the absence of trees" "2544": "handmade.cpp: Investigate this absence of trees" "2607": "handmade_asset.cpp: Determine whether LoadBitmap is thread-safe" "2677": "Use the asset_bitmap_info table" "2753": "handmade.cpp: Re-enable PushBitmap" "2796": "Debugger: Step through LoadBitmap and RandomAssetFrom" "2899": "Inspect the assets" "2997": "handmade_asset.cpp: Add the Choice rather than the Count in RandomAssetFrom" "3034": "Run the game and wonder why it was failing" "3106": "handmade_asset.cpp: Finish off the asset array set" "3153": "handmade.cpp: Set Stamp from RandomAssetFrom" "3226": "Run and note the absence of ground chunks" "3261": "handmade.cpp: Write the fail case for AllResourcesPresent" "3324": "Debugger: Look through FillGroundChunk" "3371": "handmade.cpp: Setup RenderGroup, Buffer and Task near the top of FillGroundChunk" "3416": "Run the game and recap today's progress" "3485": "Q&A" "3522": "What do you mean when you say to write "usage code first"? Also, is there any special handling of Asset 0? I am unclear on this" "3645": "You used some uint32_t in t here instead of uint32" "3701": "Are you expecting a new batch of art from Yangtian?" "3721": "Are you gonna eventually downgrade the graphics to stir up some controversy and get the game talked about on NeoGAF and Reddit?" "3792": "What are some example changes to the gameplay that would require changes to the tags?" "3833": "What certifications do you have?" "3864": "Do you ever feel sleepy when it's taking you a long time to solve a bug?" "3881": "Are you going to show the asset pipeline tools programming on stream?" "3932": "I missed the pre-stream. Did you talk about APIs like you said you would on twitter?" "3951": "What reason is there to use size_t other than int32 or uint32?" "4020": "Do you plan on implementing HTC Vive and Lighthouse support for whatever reason?" "4052": "If the asset pipeline won't be done on stream, will you still release the source for it?" "4123": "Will you do a separate isolated session on databases (mentioned yesterday)? I would love to hear your thoughts on that" "4152": "Will you talk about APIs now?" "4170": "HTC is handing you $500,000: are you doing Vive support now? Hmm? HMMM??" "4249": "Will you accept Chromatic Aberration as the best post-processing thing ever conceived?" "4371": "Why don't you support DirectInput8 for supporting good old USB controllers, instead of just Xbox360 controllers?" "4416": "If the people in this chat collectively give you $500K, will you implement VR?" "4447": "Rant: APIs, with the assistance of Dependency Walker" "5265": "Seems to me nobody at Microsoft has any idea about why Windows is still even working properly" "5543": "Isn't the huge amount of the dependencies an inevitability of complex software like a modern full OS for productivity desktop?" "5733": "Do you know that your channel runs ads for an eSports gambling site?" "5789": "Wrap it up" --- name: "day136" title: "Tag-based Asset Retrieval" markers: "40": "Recap" "82": "Casey has an itch" "103": "Goals for the asset system" "508": "Looking at the Hero Bitmaps" "649": "Classifying hero parts" "765": "Classifying facing directions" "858": "Requesting assets by tags" "1231": "Using BestMatchAsset for the HeroBitmaps" "1544": "Loading in the hero parts" "1724": "Tagging hero parts by direction" "2113": "Revisiting FacingDirection" "2197": "Blackboard: Supporting different comparison functions" "2515": "Using the actual facing direction angle" "2700": "Debugging broken directions" "2998": "Temporary fix: Shift the domain" "3075": "Tomorrow's task: Correct periodic handling" "3117": "Q&A" "3136": "It's a bit delayed, so bear with us" "3174": "Could all tag matching be periodic and then we just make the period really large when we don't want it to wrap?" "3242": "The hero has separate bitmaps for his sprite. Will this be a recurring thing for other kinds of sprites in the game?" "3285": "From a scale of 1-10 how dumb do you think the Windows API is?" "3345": "For getting the angle you want couldn't you just divide the angle by 45, giving you a number to switch on? You could go a step further and take the modulus of the number of angles you want" "3382": "Tau is clearly the superior constant. Please remove every instance of Pi in the code!" "3535": "What is your opinion on people who use spaces instead of tabs?" "3563": "hy did you use A tangent of the angle for determining the asset?" "3573": "Blackboard: Looking up an art asset" "3889": "How many spaces: 2, 3 or 4?" "3904": "Will you implement asset loading priority? For example, the player should probably load first so that you're not invisible in the beginning" "3931": "Would it be a good idea to switch to using Matrices for Rotation (so further down the line it's easier to implement scale and transform)?" "4000": "Maybe this is something I missed, but are you using cmath's atan2?" "4050": "Call it" --- name: "day137" title: "Matching Periodic Tags" markers: "108": "Demo a bug in the asset system" "185": "Blackboard: Periodic Tag Matching" "441": "Blackboard: "Neighbourhood operator"" "620": "Blackboard: "Neighbourhood distance"" "810": "Blackboard: Changing the sign of a point in the negative range in order to compute the distance of it from a point in the positive range" "923": "Blackboard: Moving a positive number into the negative" "981": "Blackboard: The whole equation for doing this neighbourhood calculation" "1211": "handmade_asset.h: Add HalfTagRange to game_assets" "1268": "handmade_asset.cpp: Set the HalfTagRange for each TagType" "1331": "Use the HalfTagRange in BestMatchAsset" "1406": "handmade_intrinsics.h: Write a real32 version of SignOf" "1417": "handmade_asset.cpp: Continue adding (Half)TagRange to BestMatchAsset" "1522": "Debugger: Step into BestMatchAsset" "1571": "Play the game and check out our new functionality" "1603": "We're kind of done" "1680": "handmade_asset.cpp: Add *FileName[] in order to loop over the bitmaps and set TopDownAlign" "1819": "Debugger: Look at the alignments" "1970": "handmade_asset.cpp: Bake that calculated alignment into the hero bitmaps" "2014": "Run the game and check out the correct alignments" "2042": "Start talking about the asset file format" "2136": "handmade.h: Add two items to the Asset streaming TODOs, and prioritise Audio" "2231": "handmade_asset.cpp: Introduce LoadSound" "2639": "Introduce DEBUGLoadWAV" "2697": "Internet: Bring up the WAVE specifications" "2743": "Blackboard: "IFF" file format" "2925": "handmade_asset.cpp: Introduce WAVE_header" "3032": "Introduce WAVE_fmt" "3158": "Introduce WAVE_chunk" "3183": "#define RIFF_CODE" "3312": "Parse the WAVE_header for its IDs" "3394": "Leave it there and glimpse into the future" "3478": "Q&A" "3510": "For getting the character sprite couldn't you just do the following? int sprite_to_load = (angle + (180 / sprites)) / (360 / sprites) % sprites" "3599": "ChronalDragon and I had a combined question about the audio asset struct. Will it need a SoundLoopable, or LoopStart / LoopEnd (with LoopEnd == -1 meaning a one-shot sound)" "3640": "Plans for implementing other audio formats like MP3?" "3785": "Wait, how exactly is MP3 patented?" "3888": "Yeah, but why would people patent a file extension?" "3932": "FLAC is 50% the size of WAV, so it's useful for lossless compression" "4116": "So is that why RAD doesn't patent any of their stuff?" "4136": "Wind things down" --- name: "day138" title: "Loading WAV Files" markers: "66": "Assets: handmade_hero_test_assets_003.zip is released" "177": "handmade_asset.cpp: Correct a mistype in WAVE_fmt" "267": "handmade.cpp: Do a DEBUGLoadWAV call in GameUpdateAndRender" "320": "Debugger: Step in to DEBUGLoadWAV" "369": "Fall foul of Microsoft Visual Studio" "453": "handmade_asset.cpp: Introduce riff_iterator to use in DEBUGLoadWAV" "628": "handmade_asset.cpp: Add WAVE_ChunkID_data to RIFF_CODE" "719": "handmade_asset.cpp: Continue on writing the usage code for DEBUGLoadWAV" "787": "handmade_asset.cpp: Introduce ParseChunkAt" "834": "handmade_asset.cpp: Introduce NextChunk" "949": "handmade_asset.cpp: Introduce IsValid" "998": "handmade_asset.cpp: Continue on writing DEBUGLoadWAV" "1045": "handmade_asset.cpp: Introduce GetChunkData" "1124": "Debugger: Step in to DEBUGLoadWAV" "1316": "handmade_asset.cpp: Remove Chunk from riff_iterator and ParseChunkAt, and instead use it in NextChunk and GetType" "1361": "Debugger: Continue on stepping through DEBUGLoadWAV" "1408": "Internet: Try and determine whether the RIFF file should end in zeros" "1610": "handmade_asset.cpp: Pad the Chunk->Size if it is odd" "1665": "handmade_asset.cpp: Subtract 4 from the Header->Size" "1721": "Debugger: Step through DEBUGLoadWAV and find that we're correctly iterating over the chunks" "1749": "handmade_asset.cpp: Assert certain data to be valid" "1808": "Internet: Find out what nBlockAlign means" "1877": "handmade_asset.cpp: Assert nBlockAlign to be 2 * nChannels" "1908": "handmade_asset.cpp: Set the ChannelCount and SampleData" "1969": "handmade_asset.cpp: Assert ChannelCount and SampleData to be valid" "2021": "handmade_asset.h: Add ChannelCount to loaded_sound" "2067": "Internet: Try to establish how to determine the sample count minus any rounding" "2099": "handmade_asset.cpp: Compute that SampleCount" "2145": "handmade_asset.cpp: Introduce GetChunkDataSize" "2192": "handmade_asset.cpp: Create arrays for our SampleData" "2277": "Blackboard: Deinterleaving audio channels in place" "2655": "handmade_asset.cpp: Write out the swizzling algorithm for the left channel" "2799": "handmade_asset.cpp: Spam in some test data" "2941": "Debugger: Check out the values in the right channel" "3047": "handmade.cpp and handmade.h: Reenable tSine" "3128": "handmade.h: Introduce loaded_sound TestSound" "3191": "handmade.cpp: Comment out GameOutputSound and use TestSound" "3322": "Run the game and hear that it doesn't sound very good" "3362": "Debugger: Step through the SampleIndex loop" "3408": "handmade.cpp: Make the Sample data be int16" "3447": "Run the game and still hear the clicking" "3470": "Listen to the sound" "3521": "handmade.cpp: Read through the SampleIndex loop" "3577": "Debugger: Step in and inspect the SampleData" "3664": "Internet: Take a look at PCM Data" "3718": "handmade_asset.cpp: Remove the test code" "3749": "Run the game and hear it more correctly" "3762": "build.bat: Switch to -O2" "3789": "win32_handmade.cpp: Set GameUpdateHz to MonitorRefreshHz / 2.0f" "3801": "Run the game and hear it all playing correctly" "3839": "handmade.cpp: Play music_test.wav" "3856": "Q&A" "3885": "You could try uninterleaving the channels in place like this: http://imgur.com/ZcDu4Tb" "3950": "Probably the second-easiest way to deinterleave is multi-pass. Swap R0/L1, R2/L3, L4/L5 etc. Then do the same with two-sample blocks, four-sample blocks, etc. Easiest way is to deinterleave directly into mix/output buffer." "3978": "Why do you need to un-interleave sound? When you play it, you still have to read both left and right values" "3999": "People are asking about the benefits of extern C? What issues does it address?" "4123": "Casey, can you please explain: (Chunk->Size + 1) & -1 ?" "4454": "Why are the samples interleaved and not flat?" "4518": "If you think of your interleaved data as an Nx2 matrix, then transposition can be viewed as interleaving. Here is an in-place way to do it: https://goo.gl/fgPmrg" "4568": "Thank you" "4685": "Why do you want to change the PCM data in place instead of compacting it to just the information you need and allocating extra space?" "4749": "Wrap it up" --- name: "day139" title: "Introduction to Sound Mixing" markers: "19": "Deciding to do an audio mixer" "258": "Blackboard: Sound and Music" "300": ""The world is filled with molecules"" "549": "Blackboard: How we hear" "653": "Blackboard: Frequency" "1139": "Blackboard: Amplitude" "1652": "Blackboard: Doing this process from the software side" "1834": "Blackboard: Mixing sounds by adding them together" "2223": "Blackboard: Optionally increasing the complexity" "2289": "Blackboard: Clipping" "2622": "Blackboard: Modulation and Interpolation" "3014": "Blackboard: Pitch" "3377": "Blackboard: Set the stage for tomorrow" "3478": "Q&A" "3502": "You said panning is just a function of volume, but could it also mix a portion of one source channel into the other output channel (for stereo)?" "3788": "Earlier in the stream you were describing audio in relation to light and you mentioned how sound is volumetric. But isn't light also volumetric?" "4328": "No special sound effects such as reverb?" "4362": "Are you going to do any work with sound analysis or visualization using FFTs? Do have any experience with that kind of stuff?" "4404": "Is their any need for an equalizer for the game's engine? I assume it would be trivial to implement." "4494": "Won't we also want at least a low-pass filter for audio coming from, for example, the other side of a wall?" "4550": "Some older sound cards could do cross-talk cancellation to try to do 3d sound with 2 or 4 speakers instead of with headphones, do you have any experience with this?" "4567": "What is a good way to get sound to bounce off objects more realistically? (i.e., walls, cars, etc.)" "4642": "Call it a day" --- name: "day140" title: "Implemented a Sound Mixer" markers: "86": "Recap and set the stage for the day" "264": "handmade.h: Introduce playing_sound and add a pointer to it in game_state" "475": "handmade.cpp: Setup the PlayingSound loop" "612": "Blackboard: Working in a 32-bit depth mixing buffer" "703": "handmade.cpp: Introduce RealChannel0 and RealChannel1" "776": "handmade_asset.h: Introduce loaded_sound" "802": "handmade.cpp: Call loaded_sound and sum the Samples in our loop" "1112": "handmade.cpp: Loop over the summed sounds, read out of them and write them to the SampleOut buffer" "1341": "handmade.cpp: Introduce SamplesToMix and SamplesRemainingInSound to handle the finite nature of the audio" "1528": "handmade.h: Add playing_sound *FirstFreePlayingSound to game_state" "1551": "handmade.cpp: Use that FirstFreePlayingSound in the PlayingSound loop" "1583": "handmade.cpp: Snap the Next pointer earlier in order to protect against the act of having it freed screw up our iteration" "1680": "handmade.h: Introduce the concept of a MetaArena" "1871": "handmade_asset.h: Add audio assets to asset_type_id" "1930": "handmade_asset.cpp: Extend the asset loading to handle audio" "2067": "handmade_asset.cpp: Introduce AddSoundAsset" "2186": "handmade.cpp: Make the new system emulate what we had at the start of the stream" "2341": "handmade_asset.cpp: Introduce GetFirstSlotID and various Get functions for Bitmaps and Sound" "2731": "Debugger: Step through the asset loading code" "2751": "handmade_asset.cpp: Set the SoundCount to be 256 * Asset_Count" "2771": "Debugger: Inspect GameState->FirstPlayingSound" "2795": "handmade_asset.cpp: Turn it up to full blast" "2824": "Debugger: Step into LoadedSound" "2907": "build.bat: Switch to -O2 and run the game" "3013": "handmade.cpp: Introduce PlaySound" "3220": "Run the game and hear our sound" "3225": "handmade.cpp: Call PlaySound upon triggering the Sword" "3309": "handmade.h: Add random_series GeneralEntropy to game_state" "3396": "Run the game and find that it almost works" "3415": "handmade.cpp: Investigate the bug" "3454": "Blackboard: Linked list" "3494": "handmade.cpp: Correctly construct this linked list" "3688": "Debugger: Step through the playing_sound linked list" "3884": "handmade.cpp: Reset SamplesPlayed to 0 in PlaySound" "3933": "Run the game and hear our sound" "3980": "Q&A" "4053": "s the sound buffer logarithmic or linear (decibel or linear values) and do we (have to) account for that in building the sums for the buffer?" "4084": "Do you already have someone composing the soundtrack?" "4192": "A reminder about the parameter order in InterlockedIncrement and the bug it covers up" "4241": "handmade_asset.cpp: Handle the case when BeginTaskWithMemory in LoadBitmap fails" "4324": "When mixing a mono sound to stereo, volume of each channel should be 50% for center panned" "4412": "Will this audio code allow you to play the same sound simultaneously (i.e. if you start the same sound before it finishes the first time)?" "4433": "The second and third parameters in the compare and swap" "4479": "handmade_intrinsics.h: Swap those parameters in AtomicCompareExchangeUInt32 and then swap them back and instead change the funtions where it's called" "4614": "The audio seems to be frame rate dependent at the moment. Could putting it in a separate thread or using interrupts (if you can), make it not frame rate dependent?" "4715": "Would you mind adding a __sync_val_compare_and_swap(Value, Expected, New) for gcc / clang" "4735": "handmade_intrinsics.h: Add tfnw's suggestion" "4850": "handmade.cpp: Play the music instead of the bloop, to demonstrate playing the same sound simultaneously" "4934": "So why does it work?" "4974": "Blackboard: Separating asset data from instance data" "5075": "Why use a linked list as opposed to another data structure like a vector?" "5152": "But can you take the output of the sound summer mechanism and play that?" "5168": "Go ahead and call it" --- name: "day141" title: "Streaming Large Audio in Chunks" markers: "0": "Welcome and thinly veiled threats" "96": "Recap of last episode and today's agenda" "286": "Brainstorming possible ways of loading large audio in chunks" "550": "Chaining sounds together" "776": "Programming the simple version that skips" "924": "Aside on loading and prefetching" "1153": "Extending asset_sound_info to refer to a particular section of a file" "1405": "Aside on terseness of typedefs for basic types" "2200": "Seamless mixing" "2768": "Pulling sound code out into a separate file" "3114": "Abstracting the audio arena" "3384": "You should apply for a (twitch) sub button" "3421": "What is your favorite genre of music and do you see it influencing the atmosphere of the final game?" "3557": "I think I missed the day you added the music. Where is the track from? Will it be in the final game?" "3608": "What is the reason you use a temporal arena in the mixer instead of a normal arena?" "4030": "We've had some new blood asking about the absence of Java. Could you please help clean the chat by doing another Java rant?" "4279": "Are you now streaming long audio assets from disk?" "4310": "I think we need a fade-out when audio stops, rather than a dead stop, to avoid a loud click" "4424": "Once upon a time the number of hardware channels available on a soundcard was important. Do most games these days don't care because doing things in software is fast enough?" "4752": "Would you ever need any kind of MP3/OGG support in Handmade Hero or is WAV OK for music here?" "4984": "Would a garbage collector help us with managing the sound buffer and chunks?" --- name: "day142" title: "Per-sample Volume Interpolation" markers: "46": "Plan for today" "127": "Dynamic asset streaming and audio mixing didn't take that much code" "217": "Public service announcement: Sometimes, writing your own code is faster than reusing other people's code" "356": "Some differences between audio and video animation and their effects on sound mixing architecture" "595": "We want to change volume over time, while avoiding discontinuities" "773": "Definition of the interface to ChangeVolume" "843": "Two ways of specifying speed of volume change: time it takes to reach target volume vs rate of change" "1280": "Using dimensional analysis to figure out dVolume" "1850": "Changing resolution back to 960x540 to remain in debug mode at a reasonable framerate" "2070": "Avoiding overshooting the target volume" "2668": "Problem of current approach: repeated imprecise floating-point addition may lead to errors" "2725": "Alternative approach: linear interpolation between beginning and end volumes" "2802": "Alternative approach: backsolving to hit the target volume at the end of the loop" "2891": "Testing ChangeVolume interactively" "3188": "Q&A" "3229": "Can you show again how you skipped a failed assertion, by going to disassembly?" "3610": "Would there be any case where you would like to increase volume non-linearly?" "3721": "So far you can just change the volume of individual sounds. Should we be able to change the volume of the master output as well?" "3806": "Will Handmade Hero support spatialization? e.g. sound mostly in left channel if on left side of the screen, sound mostly in right channel if on right side, etc." "3843": "How hard would it be to do a fade-out/fade-in for the music when the window loses focus/gets focus back?" "3909": "So what did you end up doing to dVolume if it wasn't linear interpolation?" "3928": "If you implemented Assert using ?: instead of if, you could use it as part of expressions or other such places where you can't have an if statement" "3975": "Did you already implement audio clipping?" "4054": "(clarification) Managing audio dynamic range. Yes" "4084": "With respect to Assert, I don't know why you would want to put one in an expression, but apparently that's how it's usually implemented... It can't hurt, right?" "4185": "You can't just hard-clip audio, though. If you don't use a compressor/limiter you would have to at least use soft-clipping with tanh or something" "4212": "Will you implement audio file compression?" "4295": "What would an audio compressor do?" "4425": "How much optimization would the mixer require?" "4461": "What is the difference between a limiter and a compressor?" --- name: "day143" title: "Pitch Shifting in the Mixer" markers: "26": "Recap and plan for today" "74": "Discussion on using volume changes and pitch-shifting to generate a rich soundscape with few sound assets" "419": "How to pitch-shift a sound" "554": "Compromises for minor pitch changes" "683": "Deciding on linear interpolation for real-time mixing" "805": "On the importance of linear blending" "1022": "The simple version: choosing the nearest sample" "1089": "Implementing the simple version" "1307": "(intermission) Outputting sound even when the game window loses focus" "1675": "Back to implementing the simple version" "2041": "Debugging the simple version" "2298": "Adding linear blending of samples" "2500": "Comparing sound output with and without linear interpolation between samples" "2574": "Making dSample part of playing_sound" "2695": "Flushing queues before reloading game code" "2807": "Copying strings out of the game code block to avoid crashing after hot code reloading" "2917": "Implementing PushString" "3283": "Q&A" "3328": "How would you pan a sample slightly left or right in volume?" "3787": "Would this pitch shift be animated as well, like you enter a time-dilated area and pitch-shifts in a second or two as you cross a barrier" "3842": "If you wanted to pitch-shift the music without changing the speed couldn't you just do a quick and dirty linear interpolation between the current sample and the next sample?" "3970": "Did you ever cover what would make a good test sound file for this type of mixing work?" "3990": "Do you ever use memcpy from the C standard library?" "4013": "What's the yellow Rectangle?" "4060": "What kind of sound options do you plan to include in the game? Like will the player be able to pause the game and mute the music but keep the sound effects? Or is it going to be a fixed thing like controller settings?" "4171": "Wouldn't you want to use the alternate way of animating the volume for this feature? By setting a rate, not a length of time?" "4217": "With a player running, would you connect speed of the player to pitch or look to add more sounds i.e. more steps in grass?" "4254": "Once you release this source code, this will allow people to build upon/edit to make their own games. Correct?" "4302": "You may have already covered this, but does the OS alone allocate threads to run on each core, so is it impossible to force a single thread to run on its own unique core?" "4484": "Is programming just remembering a whole bunch of commands and putting them into sequence?" "4590": "Is it too complex to add low/high pass filters via code?" "4683": "If a tree falls and the hero is not there to hear it, will it make a sound?" "4752": "Is the next thing you are going to do put the sound code in SIMD?" "4798": "Are you going to use complex numbers? I heard they're useful for sound processing" --- name: "day144" title: "SSE Mixer Pre and Post Loops" markers: "131": "Plan for today: SIMDizing the mixer" "221": "Aligning the temporary buffer" "300": "Making sure the temporary sound buffers are big enough to fit all samples" "329": "Explanation of Align16" "383": "Alignment macro for any power of two: AlignPow2" "677": "Clamping samples to the signed 16-bit integer range" "1089": "(intermission) Two's complement" "2084": "Back to SIMD" "2208": "Rounding the samples" "2257": "Downconverting from 32-bit to 16-bit integers. No clamping necessary!" "2394": "Looking for intrinsics that interleave 16-bit values" "2658": "Interleaving the samples before packing them" "2847": "Making sure we don't write out of bounds" "2940": "Debugging output using structured input" "3170": "Padding the buffer in the platform layer to make sure we always have space for overwrites" "3260": "Casey remembers that the horizontal mouse position was linked to music panning" "3292": "Getting rid of unnecessary clamping operations" "3345": "Using aligned loads and stores" "3444": "Plan for next episode" "3690": "More 2s complement. Full example" "4290": "Q&A" "4297": "Why isn't 2's complement used for floating-point numbers if it makes signed arithmetic easy?" "4595": "Are you not going to profile it too see how much faster it gets?" "4615": "When you implemented streaming in chunks of audio; I believe the code actually loads the entire file (with a platform layer VirtualAlloc) for each chunk. Is this just an artifact of the debug nature of that code?" "4653": "Does the audio make the framerate in debug mode?" "5169": "If 1111 (-1) is supposed to be less than 0000 (0) then how do number comparisons work on the CPU level?" "5559": "Do you have any tips for speeding up compile time when using multiple translation units?" "5575": "It's movsx for signed" --- name: "day145" title: "SSE Mixer Main Loop" markers: "69": "Plan for the day" "182": "Working 8-wide instead of 4-wide" "483": "Making sure the sound buffer always asks for multiples of 8 samples" "740": "Samples seen as chunks of size 8" "990": "Padding the end of the output buffer with zeros as a consequence of working with blocks of samples" "1260": "Pitch-bending forces us to read unaligned" "1535": "Updating the routine to work with blocks of 8 samples" "1999": "Seamlessly transitioning between streaming sounds by padding them with subsequent sounds up to 8 samples past their end" "2518": "Debugging pitch-shifting after the changes" "2782": "SIMDizing the main mixer loop" "3172": "Trouble SIMDizing the loads of the bilinear case" "3413": "Loading samples one by one for the bilinear case, not by blocks of eight samples" "4027": "Take a listen in-game" "4099": "Q&A" "4219": "What's in the 8 bits we've been working on? Is it frequency and volume?" "4245": "Why is there a command override Od with O2 in the build output?" "4292": "Can you skip the 0.0f*dSample and only do 1.0f, 2.0f, 3.0f ?" "4346": "What does -Od do?" "4414": "What is the "handmade_optimized.cpp" all about?" "4486": "I'm guessing that without specifying some sort of optimization flag, there will still be some optimizations done, which you want to explicitly not do?" "4529": "Is this the last stream for audio?" --- name: "day146" title: "Accumulation vs. Explicit Calculation" markers: "160": "Pitch-bending makes aligned reads impossible, so we can support looping sounds, after all" "435": "Working on chunks of 4 samples instead of 8" "1111": "Simplifying OutputPlayingSounds" "1287": "Working on the linear-blended sample load" "1893": "Writing a more robust termination condition" "2009": "Looking for the source of a failed assertion" "2527": "The problem was the accumulation of floating-point error while fetching samples" "2686": "Accurate SamplePosition" "3011": "Blackboard explanation: accumulation vs explicit calculation" "3364": "(Prestream-like) Q&A" "3451": "You're a rad dude" "3475": "What would you recommend as a good tutorial source or area to learn how to code" "3531": "Is your SIMD clear to zero faster than memset?" "4021": "Do you have a public style guide?" "4049": "I'm looking to learn something other than Java so I can have diverse knowledge. Any recommendations on how to go about doing that?" "4169": "At what point did you first feel like you could easily write software independently?" "4202": "Why is the sample index floating point? Is it for the pitch shifting?" "4216": "Why do gaming companies like Riot or Blizzard entertainment use C++ over all the rest of programming languages?" "4723": "League of Legends is written in flash" "4852": "Actually, only the login client is flash. The game itself is C++." "4928": "Also, there is a new version of Binding of Isaac that is non-flash" "4970": "Well I said air, not flash, but I guess I'm wrong either way?" "5003": "What is the difference between arbitrary and random?" "5035": "I don't know if air has the exact same runtime though? I've worked with air/flex and it's definitely the same API, but I don't know about the runtime" "5055": "("What is the difference between arbitrary and random?" followup) in the mathematical sense" "5103": "What would you rather write a game in? Java or C#?" "5141": "Have you ever smoked weed and programmed?" "5170": "The Axiom of Choice is kind of about arbitrariness and is kind of controversial" "5178": "(Question from Casey to Jon Blow) Is emergent design bad?" "5310": "(Jon answers)" "5423": "Why do you say OO is awful?" "5818": "Will HmH support "physics/simulation" and rendering in different threads?" "5837": "You make it sound like those languages have no purpose. They're great for other things than game dev" "5860": ""Arbitrary" is the bottom element of a mathematical lattice. See http://www.azulsystems.com/blog/cliff/2012-02-12-too-much-theory for details" "5875": " What do you do in order to help prevent carpal tunnel syndrome? Does it get real bad? Anything in particular you try and avoid?" "6012": "Do you know of any OpenGL resources you know of that actually explain why they do what they are doing?" "6034": "By what you said, can I conclude that you have not written a Game Design Document?" "6070": "So OO is kind of like when you design a game ahead..." "6223": "Is this project planned to be a game playable for "real" or more like "How I create games"?" "6295": "Since we are talking about OO/Programming Languages I must ask, how do you feel about Perl?" "6320": "Do you feel Minecraft was a success because of the idea rather than the execution for the first time ever?" "6416": "Dynamically-generated maps?" --- name: "day147" title: "Defining the Asset File" markers: "54": "Recap of previous episode" "98": "On managing programming time efficiently" "199": "The mixer interface with the game is not final, but we already know what it needs from the asset system" "309": "Plan for the day: definition of the asset system" "437": "Two aspects of the asset system: file management and memory management" "601": "Focusing on the asset files" "672": "Types and Tags decouple the game code from the asset table" "939": "Review of the asset system code" "1095": "Asset types reference a contiguous range of actual assets in a separate table" "1230": "Generalizing the asset system to allow for multiple ranges of the same asset type in different asset files" "1739": "Making a program that writes a dummy asset file" "1906": "One example of when to use libraries" "2908": "Simplifying the asset structures by getting rid of SlotID" "3976": "Q&A" "3999": "How many lines of code is the project so far?" "4064": "You mention LZ compression of assets. Will we write the compression algorithm?" "4101": "Are we using bitmaps for any other reason than how easily they can be processed?" "4151": "What does "union" do when used in the struct?" "4369": "Did I see an off-by-one error on assigning bitmap_id? bitmap_id Result = {...->variable++} Is that increment correct?" "4428": "Off-topic Q&A" "4434": "Opinions on specialized game development universities, like DigiPen?" "4453": "Any thoughts about Unreal Engine 4?" "4460": "How did you start learning C/C++? School or self-taught?" "4473": "Have you considered having a keyboard-cam, so we can see your lightning fingers?" "4487": "Did you program during the weeks missed?" --- name: "day148" title: "Writing the Asset File Header" markers: "38": "Recap and plan for the day" "147": "Bug determining when sounds finish playing" "628": "Rearchitecting the mixing loop to avoid this sort of bug. Removing a secondary variable to avoid having to keep it in sync" "736": "On the importance of assertions" "821": "Write assertions to catch the kind of errors that you tend to make" "936": "Back to the test asset builder" "1261": "Trick to avoid modifying lots of code to reflect the change of a variable from object to pointer" "1563": "Data that we want to include in the asset file" "1672": "Pragma-packing the file format structures" "1725": "The hha header and its magic value" "2024": "Overview of the structure of the asset file" "2320": "Using offsets and counts to access asset content" "2680": "Writing the header from the test asset builder" "2766": "Two ways of computing the offsets of tags, asset types, and assets" "3056": "Streaming files mini-rant (extended in the first question of the Q&A)" "3171": "Writing out the arrays" "3522": "Stepping through the code" "3965": "Hex editing the resulting file" "4055": "Q&A" "4082": "Why is a position for a stream a bad idea?" "4620": "Are you concerned that "trusting" the file format could have security concerns, e.g. someone could say they've made some modded assets, and give out a specially crafted .hha file that runs arbitrary code?" "4869": "What is the main difference between using asserts in your code and writing separate test functions/programs that check your results, and when do you choose one over the other?" "5022": "Will multiple threads pose any problems to reading the assets file?" "5051": "If C++ had introspection, would this be a a place where you would use it? e.g. to introspect the types you want to include in the asset pack" "5176": "Are there any specific times your streams start and end?" "5237": "Why not just read the entire file in as a string and parse it as you please, then do the same for writing" "5443": "Another option is to memory-map the file and then do as you will. Although that may not work on older consoles" "5599": "Do the mollyrocket artists ever interact with the asset packer or is it automated somehow. E.g. if they immediately want to preview how their artwork looks in game" "5636": "I was taught to use exceptions because it does not convolute the code with error checking code" "5725": "(clarification to question at 1:30:43) When I said "memory-mapped file", I meant it as an alternative to fread(), not as an alternative to streamed loading. Using fread() actually copies all data twice: buffer cache into FILE* buffer, then buffer into final destination. Copying from a memory-mapped file means only one copy" --- name: "day149" title: "Writing Assets to the Asset File" markers: "12": "Recap and plan for the day" "180": "A file is a permanently stored version of memory" "260": "Two ways of storing the asset array and the assets:" "299": "1) Going back and forth after writing each asset" "369": "2) Writing all the assets, going back and writing the whole asset array" "453": "C Run-Time library function: fseek" "587": "The CRT's fseek does not support 64-bit offsets" "1155": "Moving the BMP code into the test asset builder" "1387": "Including the math header file, after all" "1434": "Moving the sound code into the test asset builder" "1835": "The CRT's ftell does not support 64-bit offsets" "2094": "Guarding against multiple bitmap pitches" "2233": "Loading asset data into freeable memory" "2370": "C Run-Time library version of ReadEntireFile" "2475": "Figuring out the size of a file using fseek" "2565": "Skipping the first, intentionally blank, asset" "2594": "Debugging ReadEntireFile" "2899": "Switching to loading all assets from the pack file" "3035": "Approaching expansive code changes. One step at a time" "3240": "Referencing the asset file loaded into memory" "3416": "Straight casting of the header file as an hha header struct, and checking the magic value and version" "3559": "Stepping through the code" "3617": "Q&A" "3656": "How long has this been going for?" "3680": "What does flat-loaded mean?" "3829": "What is the benefit of keeping all assets in one file as opposed to making different asset files dedicated to each type of asset?" "3886": "Should there be error asserts if there are no assets that match a query? (answered at 1:05:42)" "3920": "Will you ever make games to make profit off?" "3942": "The latter (about the assets)" "4172": "Off-topic Q&A" "4183": "Where did you learn to code?" "4195": "How long have you been coding?" "4199": "Is this what you do full-time? Or do you work for a company?" "4233": "Will the game be multi-player or single-player? And will you be able to code your character, kind of like CodeSpells, like the name "handmade hero" would suggest?" "4306": "Why is your bio webpage not viewable without javascript?" "4383": "What is a bit map?" "4549": "Have you been doing this all your life?" "4552": "What is the Windows 10 release date?" "4559": "What is your day job? And do you enjoy it?" "4573": "What is Overlapped IO?" "4593": "In that case (referring to question at 1:03:49), why do other developers break up their assets in separate files?" "4647": "Would having separate files assist with modding or patching?" "4696": "Is Mike Acton's Data Oriented Design any different than Compression Oriented Programming?" "4806": "One reason to split files is to get around the FAT32 4GB limit. Another reason might be if your pipeline allows audio devs to update their pack file for the game w/o needing or messing with other parts of the game (models, textures)" "4860": "Where can we read about the actual plan for the game? (gameplay)" "4866": "Are you using any C++ plugins for Emacs?" "4879": "Won't the game have to wait until all the assets have been decompressed before the game can start?" "4927": "Why are you using Windows instead of Linux?" "5458": "Can you say something on stream to get reddit angry; they're already complaining about your OOP statement" "5483": "But you can code on Linux for Windows very easily, right?" --- name: "day150" title: "Loading Assets from the Asset File" markers: "27": "Recap and plan for the day" "131": "Loading the asset array" "380": "(intermission) Simplifying asset-related structs" "684": "Back to loading the asset array" "713": "Storing the base of the file" "736": "Loading the asset type array" "882": "Removing the call to DEBUGLoadBMP" "1156": "Removing the call to DEBUGLoadWAV" "1355": "Testing the changes" "1406": "Let's load only what we need, not the entire asset file" "1450": "Flat-loading the asset tags and the assets" "1667": "AssetTypes are not flat-loadable" "1722": "Defining the file API" "1774": "Recipe for a good API: write the usage code first" "1920": "The platform layer takes care of knowing the location of the asset files" "2333": "Allowing all operations on files and checking for errors just once" "2462": "Merging the contents of asset files" "2671": "Another opportunity for centralized error handling" "2858": "Informing the OS that we are finished using the list of hha files so that it can free any associated resource" "2951": "Organizing our assets by asset type by looping multiple times over all files" "2991": "Do this in a super janky way" "3330": "Including a TagBase in the asset_file struct to rebase its tags" "3622": "Q&A" "3691": "What's your general rule for making a variable a pointer versus not?" "4284": "I don't completely understand your aversion to using the C standard library... is this just a hmh thing for teaching? Or do you just never use the standard library?" "4541": "How and where will user save data be stored?" "4611": "Off-topic Q&A" "4615": "What keyboard are you using?" "4625": "How long have you been developing games?" "4637": "Why brown switches over blue?" "4663": "What did you had on your arms?" "4674": "Do you like dogs or cats?" "4691": "How far do you think you are in terms of stream days from implementing game logic in terms of play vs platform?" "4727": "I just got two Rpi2s, what do you think about the Rpi2 in general?" "4735": "What do you think about Intel INDE?" "4808": "End of the off-topic Q&A" "4835": "On the joy of building your engine from the ground up" --- name: "day151" title: "New Platform File API" markers: "47": "Recap and plan for the day" "244": "Review of day 150's code" "556": "Loading the asset arrays" "588": "Overview of the tag index rebasing mechanism" "704": "Setting the file's TagBase" "916": "Rebasing the asset array" "1100": "Reading in the hha_asset data" "1205": "Defining the file functions in the platform layer" "1357": "Defining the platform_file_handle and the platform_file_group structs" "1512": "File-related platform-specific functions" "1607": "Defining PlatformNoFileErrors as a macro" "1829": "Placing the new callbacks inside game_memory" "1906": "Platform API globally available to the game" "2205": "Prerequisite wiring to start implementing the win32 version of the new file functions" "2512": "It's no longer necessary for the threaded worker to deal with the asset metadata" "2590": "The work orders for bitmaps and sounds are reduced now to loading a chunk of data, so they can be merged into a single work order type" "2688": "Swapping to the new work order type with the _old_ version of the file loading routines to minimize the amount of debugging" "3105": "Reserving space for bitmaps" "3178": "Filling out the work order struct" "3612": "The win32 file routines are still not finished but our time is up, so let's leave the code in a running state" "3695": "Q&A" "3712": "With this system, is it possible to add an updated version of an asset in a new .hha file without modifying the original? How would the IDs work in this case?" "4012": "What will get rid of the initial flicker of the character at startup?" "4085": "As a programmer implementing a game with fairly simple graphics, any suggestions on finding somebody to commission art assets from or similar if you don't happen to know a good digital artist?" "4132": "End of Q&A" "4142": "Review of tasks left to finish the asset system" "4283": "Review of upcoming tasks" --- name: "day152" title: "New Win32 File API Implementation" markers: "27": "Recap" "70": "Plan for today" "143": "Asset metadata is already loaded, so LoadBitmap and LoadSound reduce to just fetching the data" "238": "Getting rid of LoadSound" "382": "(intermission) Forcing order of reads between checking if an asset is loaded and accessing it" "477": "(intermission) Implementing CompletePreviousReadsBeforeFutureReads" "595": "Back to removing LoadSound" "814": "Copying the contents of assets into the right place in memory" "861": "General-purpose memory copy function" "981": "Setting the channel sample pointers" "1077": "Testing the changes. There's some strange clicking bug going on, probably not related to today's changes. We'll do the debugging later" "1181": "Asset background loader with tag matching in 430 lines of code!" "1378": "Avoiding loading the entire asset file into memory" "1404": "Assets need to be rebased and pointed to the appropriate file through a file index" "1516": "Finding a good place in the code for the asset struct" "1654": "Filling in the asset struct" "2016": "The asset struct is just an hha_asset augmented with a file index" "2109": "Don't design architecture up-front" "2210": "Implementing GetFileHandleFor" "2348": "File I/O code is simple. Assuming we don't get it wrong, we'll save time by writing it now and testing it together with the code we just wrote. The alternative would involve writing some extra test code" "2496": "Implementing the platform functions" "2603": "We don't close files, so there's no need for a Win32CloseFile function" "2645": "Win32OpenFile" "2953": "Win32ReadDataFromFile" "3021": "Overlapped I/O" "3225": "Windows can't do reads bigger than 4GB. We don't plan on reading assets of that size, but let's assert against that situation, just in case" "3323": "Win32FileError" "3407": "Ignoring file operations on bad handles" "3488": "Testing today's code" "3549": "Quick step-through" "3600": "We hadn't read the header yet!" "3734": "Visual Studio fails to show size information on symbols outside the current running executable" "3900": "The null asset triggers an assertion. We ignore it for the moment" "3946": "It (mostly) works!" "3985": "Q&A" "4045": "What do you use when you need something more dynamic than arenas? Default to VirtualAlloc/malloc? Something completely different?" "4173": "How "handmade" are you going to go on the Linux version?" "4250": "Kind of off-topic do you usually have that much luck not getting bugs?" "4382": "Do you usually design an API by just implementing it, or do you try to define the interface first?" "4549": "What is "usage code"? Basically everything down the line that awaits to be fed data?" "5242": "Do you feel that a lot of the common programs today have "bloated" code (much unnecessary code or something along those lines), and/or that coders need to learn to simplify/barebone their code?" "5262": "Doesn't anticipating the usage of the API require decades of work?" "5594": "So basically when you're about to make shoes for a monster, you don't assume how many legs or toes it has, let it stomp around and then use the footprints to make the shoes" "5624": "Suggestion: call this "Snuffy-oriented programming"" --- name: "day153" title: "Merging Multiple Asset Files" markers: "25": "Recap" "107": "Plan for today" "202": "Guessing the origin of last stream's bug" "327": "Examining the test asset builder" "447": "AssetCount is off by 1 and null asset is not loaded" "519": "Correcting the asset count" "596": "Building the null asset" "668": "We're good to go" "687": "Testing asset merging" "729": "Taking the null tag into account" "1045": "Splitting the test asset file to test the merging procedure" "1368": "Loading just one of the files" "1513": "AssetTagCount was not initialized (although that is not the source of the error)" "1545": "Avoiding uninitialized variable bugs" "1721": "The actual bug: not clearing the asset types array in the test asset builder" "1882": "Testing the merging code. There's still a bug" "2072": "Remapping the next id to play to take into account multiple asset files" "2552": "Deciding against remapping the next id to play in favor of explicit looping and chaining of sounds" "2892": "Implementing GetNextSoundInChain" "3110": "Q&A" "3165": "Can we do advanced and then looped sounds?" "3294": "If you're doing the id.value += 1, won't you eventually loop off the last sound asset?" "3375": "Can I watch when you first started writing this game?" "3386": "(intermission) Examining an assertion raised when SamplesPlayed exceeds SamplesCount in pitch-shifted sounds" "3636": "What is the next thing you have planned after assets?" "3720": "How do you determine whether to fix a bug or keep moving forward?" "3850": "If I decide to go for a PhD or something in the future, will you give me the blessing to write about Compression-Oriented Programming?" --- name: "day154" title: "Finding Assets Files with Win32" markers: "23": "Recap and plan for today" "159": "Review of related code" "243": "Getting rid of hardcoded file names" "322": "Listing file names on Windows (FindFirstFile)" "535": "The lpFileName parameter can include wildcards" "654": "Listing the rest of the files (FindNextFile)" "741": "Guarding against invalid handle values" "828": "Invoking FindClose on the file handle returned by FindFirstFile" "910": "Structuring the file loop to be more uniform" "990": "(aside) Textbook horrible API design" "1169": "Problem: we don't know how many files there are until we have looped over them" "1233": "Revising the file API. There's no need for random access of files. Sequential access is enough and is cleaner to implement" "1288": "Preiterating the files" "1351": "Allocating space for the win32 opaque data segment of the platform_file_group struct" "1412": "Discussion on extensible platform non-specific types. This type of "space saving for dynamic unions" can be implemented using C++ inheritance, but we will encounter other types that can't" "1591": "Freeing the platform_file_group" "1867": "Second iteration to load the files, now that we know how many of them there are" "2226": "Jumping to the definitions of windows system calls using Visual Studio" "2292": "Choosing the ANSI versions of system calls and structures" "2454": "Getting the file names" "2468": "Testing the code so far" "2668": "Parameterizing the file extension" "2765": "Write your own string system if you work with strings frequently" "2917": "Possible extensions to the file API" "3007": "Q&A" "3075": "Does the save file need to use this system now?" "3149": "How do you feel now that you finished this?" "3207": "Socapex insists that the STL *is* the language and that you therefore should use "strings" from it" "3392": "Could you elaborate on the union style inheritance you mentioned? In the same vein, will entities end up being unions?" "3566": "What about updating the asset file with more files? How do you manage a ton assets as in knowing what is where?" "3609": "Will the ASCII version of FindFirstFile work even if the full file path has unicode in it?" "3680": "Will pre-rendered fonts be included into the HHA file?" "3686": "Is this the new Call of Duty?" "3766": "Does the requirement to call FileClose() make more sense when you consider that FindFirstChangeNotification/FindNextChangeNotification/RefreshDirectory are part of the same API?" "3902": "How are you doing the audio?" "3950": "You wrote code for "Lineage Forever"? Any comment on writing it on the game/any other Lineage games? Lineage 1 pretty much sparked my entire career as a computer scientist/programmer" "4122": "What's after the asset file loading?" "4138": "Why do you use #defines for things like PLATFORM_GET_ALL_FILE_OF_TYPE_BEGIN instead of just normal function call?" "4203": "I have not followed the latest episodes due to I actually watching it from the beginning. But is there any like crypting in savefiles regarding cheating, etc?" "4292": "Are there any books on game programming or general programming that you would recommend?" "4433": "What do you think about "Game Engine Architecture" by J. Gregory ? The books looks solid" "4450": "(Referring back to Q at 00:59:26) I meant the artist is making files how do you track what you added and what you didn't. What assets have changed. and need updated kind of thing?" "4542": "Is the graphics double-buffered?" "4625": "When are you going to stream your hands coding? Would be neat. You talked about doing it some time" "4657": "(Referring back to Q at 01:10:03) Well just because people would know how to beat the encryption, doesn't mean it would be a bad thing to teach in this series" "4732": "Have you read "The Tao of Programming?"" "4739": "Does it tear with Aero disabled?" --- name: "day155" title: "Introduction to Particle Systems" markers: "24": "Recap" "49": "Three possible subjects for today's stream" "283": "Let's do particle systems!" "385": "Introduction to particle systems (blackboard)" "567": "Particle systems are used to represent objects with no specific shape" "715": "Emitters and particle behavior" "835": "On the shape of particles" "879": "Overview of simple particle system implementation" "1019": "The particle struct" "1160": "Writing the particle system test loop" "1210": "Rendering and then simulating VS simulating and then rendering" "1332": "Rendering particles" "1504": "Simulating particles" "1562": "Particle placement" "1739": "Inspecting the simulation and drawing of the particle system" "1768": "Drawing particles using the shadow asset" "1976": "The hero is now the emitter" "2338": "Changing colors" "2634": "Introducing randomness into the velocities of particles" "2660": "Using a new random series just for effects" "2825": "Tweaking the velocities" "2963": "Fun selecting different sprites" "3012": "Color randomization" "3233": "A more explicit way of ramping colors up and down" "3659": "Q&A" "3694": "For a while I have felt that interpolating particles in RGB leads to results that are dull and muddy. I have been wanting to try YCrCb or maybe even LAB sometime. I guess you can compensate via splines through RGB but I think you'd be doing a lot of tweaky work all the time to get better results (even though YCrCb is just a linear transformation, I think there's a substantial amount of skew.)" "3789": "Will particle pre-warming be supported?" "3863": "When you were messing with the z direction, it seems kind of like a puddle on the ground" "3875": "Ever messed with using some kind of a stateless system of doing this? Like one function parameterized by another function?" "3905": "Is rain a particle system?" "3913": "I wonder if head particles like this could be used in the game... for example as an effect of magic related to disguises. Like, when you dissolve the disguise of the Superfish" "3932": "Witness is RGB and probably too late to change, but we don't rely on wowee particles much" "3989": "Z still points towards the screen" "4022": "Does anyone ever use layers? Or just Z-sorting?" "4038": "At what time does Handmade Hero stream? I saw this on the front page and it seems interesting" "4077": "Maybe for the Galaga game I will switch to HSV..." "4110": "Will these videos help someone learn C and C++ who has absolutely no experience?" "4236": "Have you, or will you explain how shaders work?" "4264": "Will these particles be able to react to things like impacts?" "4304": "How many particles at the moment?" "4318": "How many particles till we see a noticeable slowdown?" "4440": "Are you using Emacs outside of Visual Studio or inside of it?" "4450": "When do you plan on implementing a way to adjust the position of the individual particles when the entities move?" "4502": "What made you pick C++ over C#?" "4555": "What parameters will you tweak with curves? Scale, position, color, rotation, external forces, etc. Will the curves depend on time only?" "4636": "How many times have you said "right" in this broadcast?" "4670": "Is your .emacs config open source?" "4685": "Can you explain what procedural level generation is? Are there other types of generation, and if so what are the differences?" "4734": "What do you think about using Unity as a platform layer and using all your own logic?" "4797": "Why do you pronounce "nightmare" as "night mirror"?" "4807": "Do you have someone making the game assets for you or are they self made?" "4817": "Will you be making development tools for Handmade hero, like a map editor?" "4833": "(Referring to Q at 1:17:50) I mean is your config *public domain*? Can I give it to someone who'd like to get started with Emacs? I myself preordered ages ago, best 15$ expenditure of my life. NO CONTEST. <3" "4856": "(Referring to Q at 1:18:54) You can use DLLs. I have done this!! Much using rust, fyi" "4915": "You went from two-k on my name to zero-k. A single one would be appreciated ;D" "4952": "I mean the particular flow or direction is now from bottom up. Feels like its not hard to do left to right for example" "5042": "I think it's like GNOOKLES, but with a K sound instead of G" --- name: "day156" title: "Lagrangian vs. Eulerian Simulation" markers: "14": "Recap" "82": "Plan for today" "168": "Adding acceleration and taking it into account to compute new positions" "387": "Bouncing particles off the ground" "596": "Modeling loss of energy" "840": "We want our fountain to be more fountain-like" "1194": "Writing special-purpose code to achieve the desired behavior" "1770": "Considering the interactions among particles instead of simulating particles in isolation" "1841": "Two raw categories of physics simulations: Eulerian and Lagrangian methods" "1885": "Lagrangian: Simulation of the motion of particles through space" "1969": "Eulerian: Simulation of density and mean velocity of particles at specific locations in space" "2161": "Lagrangian methods are bad at handling density" "2200": "Eulerian methods don't keep track of the properties of individual particles" "2266": "We'll resort to a mixed Eulerian-Lagrangian method" "2325": "We could use the density gradient from an Eulerian representation to compute the horizontal push of particles in the Lagrangian representation" "2577": "Let's implement it" "3057": "Drawing the density field" "3603": "Dispersing particles taking into account cell density" "3805": "Discussion of possible improvements to the simulation" "3840": "Taking advantage of the density gradient to achieve better results" "4080": "We still don't use the mean velocity of particles inside each cell" "4133": "Q&A" "4158": "I suppose adding some friction to dP.x might help" "4241": "Try reducing the size of the individual cells" "4403": "The back of the head would make a better particle than the side of the head" "4584": "If you're going to alter the GridScale, you probably need to scale Dc by it too." "4622": "Did you ever add a way to tell the music to shut off or did you just disabled it?" "4642": "What would happen if the particles were spawned between two cells? Would that cause an effect where everything would just not bounce off each other anymore?" "4674": "On API design: You recently emphasized "Write the usage code first" and then the implementation later. While compression oriented programming is about writing code first and then compressing it, pulling code into functions where necessary, allowing the API to evolve out of that process. They seem like two contradictory methods. Are they? How do you decide when you're using one or the other?" "4978": "Would it be possible to split the fluid computation across two frames. Like use the first frame to accumulate velocity and momentum changes and the second one to resolve them?" "5022": "Does the size of the grid relative to each particle matter much?" "5070": "(Referring to Q at 01:17:22) Say you're deciding whether to bounce the particles off based on the density now, then if the particles were spawned between 2 cells, wouldn't the density be halved and not bounce off anymore?" "5182": "Would simulated annealing work for this issue?" "5196": "Doesn't writing usage code first imply simplicity in API calls? Doesn't this box you in when trying to create persistent things on the stack? All complex initializations for persistent objects have to be done somewhere. If done on the stack, how do you persist complex data structs without using static?" "5266": "Current simulation is in pixel space?" "5276": "Are pre-rendered effects viable?" --- name: "day157" title: "Introduction to General Purpose Allocation" markers: "18": "Plan for today" "88": "Our asset memory management problem can't be solved by a garbage collector" "156": "Asset memory management (blackboard)" "220": "A good way to think about memory management" "604": "The amount of memory we need is larger than the amount of memory we have. We have a Virtual Memory problem." "901": "Stacks and GC can't help us in this situation" "992": "Memory fragmentation" "1160": "In a world were all the assets were the same size..." "1280": "In our case assets are not the same size, but we could find ways around that" "1415": "We could have a big sprite sheet and page the chunks in when they were needed (similar to Megatexture)" "1674": "Another option: A variable allocator. It could defragment memory or merge contiguous freed spaces. We're choosing this one for educational reasons" "1896": "Overview of the variable allocator" "2058": "Running out of memory on purpose" "2234": "Restructuring loaded_bitmap and loaded_sound to move asset data inside asset_slots" "2981": "Moving asset data inside asset_slots" "3174": "Determining ahead of time when we're going to hit our memory limit" "3240": "We can't free assets to make room for new ones from inside a call to LoadBitmap" "3335": "We can mark bitmaps as freed between frames. Two options: a) deferring LoadBitmap calls till the end of the frame and b) keeping some amount of free space to make loading always possible" "3464": "Q&A" "3477": "It's official: Assets are now handles" "3517": "Would there be a benefit to using a 2-level cache for storing compressed and uncompressed assets?" "3575": "Is there any performance reason to not use malloc and free?" "3652": "Are there technical terms for the memory emptiness assurance algorithm?" "3677": "Can you talk a bit about what new / delete actually does and when to use them?" "4353": "Could you briefly comment on how viable it would be to recast the problem as one of asset packing? Split sounds into fixed-sized chunks and dice bitmaps into fixed-size tiles, so that all of the tiles are of a reasonable size. Group related assets together so they are loaded together. That sort of thing" "4456": "Is there a real "philosophy" difference between using smart pointers and garbage collection? Or are smart pointers just a way to implement garbage collection?" "4772": "What about RAII?" "5382": "How about vibration effect assets?" "5390": "What is the difference between a megatexture and a texture atlas?" "5433": "Do you object to use of explicit vtables, like you would have to use in C?" "5475": "Would thinking about asset allocation in terms of the maximum amount of pixels that can be displayed on screen at one time be worth it (for instance with your 16MB safety buffer). So you tailor the asset loading to load assets at a resolution proportional to the distance to the camera and operate under the assumption that only a fixed number of things can "physically" occupy the high-res space and so on for medium, low, etc." "5553": "(Referring to Q at 01:12:33) The thing I didn't see was grouping small related assets together so they fit in one allocation unit." "5584": "Is this still the same blackboard file from day 1? Is there a fully zoomed out view and how much RAM is that program consuming now with all your current doodles?" --- name: "day158" title: "Tracking Asset Usage" markers: "18": "Recap and plan for today" "72": "Using the OS's virtual memory system to solve our memory management problem" "267": "Tracking memory load" "291": "Using an allocation scheme that gets the memory from the OS and returns it on eviction" "499": "Implementing platform_allocate_memory" "626": "These changes break the looped live code editing feature" "777": "Two approaches: a) deferring LoadBitmap calls till the end of the frame and b) keeping some amount of free space to make loading always possible" "820": "Tracking amount of memory used in the asset system (AcquireAssetMemory)" "916": "RealeaseAssetMemory requires us to provide the size of asset to free" "1096": "Using the platform calls instead of the memory arenas" "1157": "Tracking memory usage and freeing memory at the end of the frame (EvictAssetsAsNecessary)" "1300": "Evicting the least recently used asset" "1398": "EvictAsset" "1604": "Distinguishing between bitmaps and sound inside AssetState" "1775": "Computing the amount of memory taken by an asset" "2111": "Getting rid of duplicated calculations" "2501": "Figuring out the location of the chunk of memory to free" "2752": "Doubly linked list to keep track of least recently used asset" "3129": "Doubly linked list theory (blackboard)" "3235": "AddAssetHeaderToList" "3381": "Semantic setup of pointers" "3433": "RemoveAssetHeaderFromList" "3738": "Initial sentinel setup" "3873": "We should avoid evicting locked assets" "4052": "Types of doubly linked lists and overview of their implementation" "4200": "Q&A" "4205": "What function owns the pointer to the head of linked list?" "4216": "Isn't a linked list what you're always told not to do if you're care about the cache at all?" "4305": "Could the platform_allocate_memory function allocate a few bytes more than requested and store the size there to avoid it having to be passed to the free function?" "4327": "Having a list header at the end of each asset struct, wouldn't that invalidate the cache a lot, when processing the list, since asset structs are potentially large?" "4394": "In RemoveAssetHeaderFromList, would it make sense to zero out the prev and next pointers of the header that is being removed, or is it just unnecessary cleanup? Are there pros and cons to this?" "4436": "Will there be a fountain of heads somewhere in the actual game, possibly as a Halloween item?" "4443": "Is Twitch your full-time job?" "4447": "How will you re-enable the live code reloading after this is done?" "4513": "Can you briefly go over inlined functions?" "4580": "Which classic data structure do you enjoy implementing the most?" "4628": "Does/will this system support hotloading of assets?" "4718": "Does it make sense to write your own non-block dynamic allocator instead of using the memory system of the OS?" --- name: "day159" title: "Cleaning Up the Loaded Asset Infrastructure" markers: "22": "Recap and plan for today" "122": "Preventing eviction of locked assets (those used in background tasks)" "246": "We never lock any asset; let's lock some" "421": "Not locking sounds" "475": "The render group knows whether an asset should be locked or not" "501": "Safeguarding against caller mistakes" "761": "Preventing the eviction of assets before they are completely loaded" "954": "Testing the changes" "986": "Moving the most recently used asset to the front of the linked list" "1324": "Getting the header from the slot is tricky" "1769": "MoveHeaderToFront should only affect loaded bitmaps" "1814": "Deciding to clean up the loaded asset code" "1830": ""Locked" as a flag, independent of asset loading stage" "2208": "Checking the commit size of the game on the Windows task manager. Casey's head gets in the way; see Q at 01:01:43" "2346": "Simplifying the loaded asset infrastructure" "2429": "Merging asset slot and asset" "2664": "Condensing everything necessary to work with an asset into the asset header" "3169": "Storing the size of the loaded asset instead of its type" "3241": "Some debugging" "3519": "Removing GetSizeOfAsset" "3655": "Q&A" "3703": "Your head was over the window when you were looking at the commit size" "3779": "The linked-list way of computing least-used asset seems like a simple and neat trick. What are its drawbacks?" "3958": "Garlandobloom may be too drunk today" "3971": "Can you explain the code in which you changed the asset loading so that it stops blinking (the bitmaps and sounds)?" "4433": "Will there be a concern of cache misses while manipulating the doubly linked lists every frame?" "4516": "You've got a TODO about the size of the audio asset struct. How important do you think it is to keep structs compact? -- (Casey undoes the size shrinking of LoadedBitmap, since now it's included in the asset header and not in the asset slot (blackboard))" "4820": "Do you have a hard drive to check this system on it?" "4838": "Is there a problem setting the asset header to null after unlocking it? I thought there was some background loading of some stuff" "4879": "Is the heap and the stack just different sections of RAM, managed by the OS? Also, if so, do different programs ever share stack space? Would you please shed some light on this or point me to some video of yours that I missed?" "4945": "I'm confused as to what the memory layout will be after using the doubly linked list for a while? The memory will fragment eventually as of now, no?" "5012": "Couldn't we use just use a 'IsLocked' bool, inside 'Asset->Header' struct?" "5030": "Won't this method of swapping the assets cause memory fragmentation?" "5267": "So something like this can't happen? Asset evict function is called, release happens, unlock happens, thread context switches to loader, something gets loaded into that slot with some header, thread context switches back, header is cleared to 0" "5437": "Is it possible that, due to the kernel caching disk accesses, we're paying more than once for each asset? Like, after we evict an asset, is another copy of it likely to be cached in physical memory because of the OS's caching of the pack file?" --- name: "day160" title: "Basic General Purpose Allocation" markers: "13": "Recap and plan for the day" "114": "Plan for today: Writing our own general-purpose memory allocator" "252": "Ode to stack memory allocation" "333": "The asset system needs a more sophisticated memory allocator" "405": "Closer look at asset eviction and memory fragmentation (blackboard)" "641": "Overview of our approach" "781": "Thinking of our available memory in terms of free fragments" "865": "Merging contiguous free blocks" "972": "We won't be performing small allocations" "1010": "Every block will keep information of neighboring blocks" "1123": "A possible way of implementing the allocation operation" "1452": "We can call EvictAssetsAsNecessary from inside AcquireAssetMemory!" "1724": "Modifying AcquireAssetMemory to work with our own memory" "2168": "Evicting assets to make room for a new one" "2239": "Keeping track of the location of our assets" "2446": "Doubly linked list of memory blocks" "3012": "FindBlockForSize" "3146": "Conditionally splitting the memory block used to store an asset as a function of its remaining capacity" "3395": "Recovering memory blocks inside ReleaseAssetMemory" "3495": "Q&A" "3580": "Given that this is an optimization problem, it seems like we'll want to have a system for profiling asset use and eviction (and check its output periodically as the game and assets grow over the next year or so). Should this be on the agenda in the near term?" "3673": "I'm not clear on what happens in the else when we fail to find a block, could you go over it?" "3823": "Why do we need to check the remaining size > threshold ? Why not just use the remaining size if it satisfies the request size?" "3966": "How come this memory management system is strictly limited to game assets and not other things as well?" "4001": "What will the GUI handle? (Answered at 01:11:18)" "4012": "If this were a commercial project, would it make sense to use malloc instead here, or write your own anyway for managing assets?" "4170": "Any possibility of using Markov Chains for the game or game engine?" "4187": "It's looking like Vulkan, if it gets released in a timely manner, is going to be a good choice for hardware rendering. I just read that you have control over all memory to avoid any unknown allocations "Explicit memory management in Vulkan allows applications to use custom allocation strategies. For example to allocate all memory up-front and avoid any allocations during rendering"" "4268": "Have you thought about having a "prefab" asset that people could use to make more complex assets, like a whole house with functional doors?" "4279": "(Referring to Q at 01:06:41) The GUI mentioned in the TODO list" "4308": "You keep saying "split the block in half" What do you mean? 'Size = Size/2'?" "4416": "(Referring to Q at 01:09:47) This is where I read it from: http://blog.imgtec.com/powervr/trying-out-the-new-vulkan-graphics-api-on-powervr-gpus" "4507": "Will the debug GUI have a cool console like Quake/Unreal?" --- name: "day161" title: "Finishing the General Purpose Allocator" markers: "21": "Recap and plan for today" "106": "We will need to debug the changes from the past episode" "221": "Simplifying some of yesterday's code" "454": "Finishing the merging of the freed blocks" "614": "Implementing MergeIfPossible" "961": "Modifying AcquireAssetMemory to check if the asset we are loading fits inside the newly freed space" "1007": "We're good!" "1156": "Potential problem of this general-purpose allocator: The linked list could be too long to walk on each allocation" "1533": "Fixing an error in OpenNextFile: If the platform layer failed to allocate the file handle, that function would fail to report the error" "2148": "Working with asset files containing Unicode characters" "2281": "On the importance of not exposing the concept of filenames to the game code" "2426": "Making the code work properly with Unicode file names" "2548": "wchar_t" "2861": "Isolating the game code from the concept of file extensions" "3184": "Q&A" "3206": "First rays of Moscow sun bid you Good Evening, Casey. I humbly request to be granted two off-topic questions (maybe near the end?)" "3235": "I asked a similar question yesterday, but I guess it wasn't clear. Have you thought about how the asset system could work with 3rd party mods? Say someone wants to make a mod that adds new graphics, sounds and/or game logic. How hard would it be to implement a mod loader, Steam Workshop support, etc?" "3323": "Should there be a way to say if one of the hero assets are loaded then they all should be loaded and not evicted?" "3390": "Might be off topic, but why exactly do you have typedef'ed functions in the code?" "3458": "Did you see this Nostalgia Critic Wicker Man (Cage in a bear suit) review? www.youtube.com/watch?v=vj_CRnwJTk8" "3474": "Can we get a visual display of the loaded / unloaded chunks of asset memory when we do the debug stuff?" "3490": "I would like to hear what your definition of enumeration is, if you will" "3524": "Good evening Casey. Does Windows 10 change the coding (if you know)?" "3572": "On MergeIfPossible, when you pass the checks and do the merge, you add the size of the header plus the size, but on the line before that you check that the (size + header) matches, but the size should already include the header. Can you explain why that is?" "3796": "What's the cause of the depth error you get on rendering?" "3826": "You know I'm the biggest fan of the series, but I suspect for complete newbies the current way you construct the game makes little sense. Consider this: you know how to make a game, so you methodically cross over a check-list of components you know by heart (mostly). What would probably be easier and more graphic for larvas to grasp is to make a little functional game(title screen, game loop, game over, start over, etc) and THEN iterate upon it. It's more visual and having a little game that evolves every day little by little keeps the maker motivated, as opposed to a pro that knows what the game should look like in the end" "4054": "Did you ever play Freelancer?" "4081": "Have you seen Kung Pow?" "4113": "Which version of Visual Studio are you using at work?" "4140": "Will that point in time see a new intro trailer with an old motherboard being pulled from the attic, engine booting up and Handmade Hero announcing the completion of the engine, perhaps with a nice sine scroller and particle effects?" "4166": "Is font rendering around the corner?" "4191": "How do you render without instantiating a brush object?" "4260": "Will you be going the easy way and using Bitmap fonts, or will you be implementing TTF?" "4328": "Do you know anyone by the name of Andre Lamothe?" "4359": "Are you going to implement distance field font?" "4511": "Is it worthwhile to try to make a game only using pure functions, i.e. no side effects" "4633": "Will you cover non-mono-spaced fonts and font kerning?" "4733": "(Referring to Q at 01:15:11) Functional game: The state is an argument and a new state is returned" "4905": "How much of the code you have written so far can be ported to 3D easily?" "4949": "(Referring to Q at 01:18:53) At least in Haskell, the "pure functional" part is hidden away from the IO stuff via a mathematical concept called "Monads"" "5037": "What do you think of a graphics system that intentionally simulates Mode 7?" --- name: "day162" title: "Introduction to Fonts" markers: "62": "Recap and overview of upcoming debug work" "143": "Plan for today" "246": "Test-driven vs visualization-driven game development" "378": "Fonts from the ground up. What are font files?" "650": "Fonts describe a mapping from character set encoding to outline shapes" "742": "ASCII/ANSI encoding" "895": "Unicode" "969": "Pros and cons of Unicode" "1163": "Unicode codepoints" "1261": "Basic typography (baseline, maximum ascenders and descenders, line height)" "1411": "Kerning" "1430": "Monospace fonts" "1546": "Proportional fonts" "1737": "Kerning information" "1945": "Hinting" "2132": "Ways of using fonts inside Handmade Hero:" "2175": "1) Load TTF and tesselate the glyphs into an outline made of triangles" "2277": "2) Load TTF and perform implicit rasterization" "2492": "3) Use prerasterized fonts" "2627": "Approaching prerasterized fonts" "2821": "Plan for the next episode" "2967": "Q&A" "2993": "Aren't there licensing concerns with fonts?" "3200": "Will you support Unicode in Handmade Hero?" "3210": "Could we not pre-rasterise our fonts whenever the resolution is changed / at run time basically?" "3245": "Will you be writing something using the font before you code the actual font reading etc?" "3270": "Q: Will classic bitmap fonts remain relevant in the coming years or will we just start flat out with vector fonts forever more?" "3304": "Are you doing quantum mechanics?" "3310": "Did you ever try making a font yourself?" "3321": "Will you have unique fonts made for the game?" "3332": "If you had multiple font families and were pre-rasterizing them, can you stuff them into one file?" "3349": "Can I come live with you and you tutor me?" "3357": "How are combining Unicode characters that some languages have handled?" "3371": "Blackboard: Combining glyphs" "3490": "I became a much happier person once I started rasterizing fonts on the fly all the time. So much better" "3516": "A bit off-topic, what makes code "publishable"? You said you wouldn't publish the current win32 platform layer. Exactly why not?" "3594": "Will you be writing your own pre-rasterizer from scratch, or using a 3rd party tool?" "3607": "In which episode will you implement Unicode skin tone emoji modifiers?" "3652": "How much time do you spend preparing for each stream?" "3657": "If you were to have a loot history or story line history - you mentioned 40px - if you wanted to allow users to adjust this UI, would you still do pre-rasterized? At what point would be the threshold for including a proper non-rasterized version?" "3708": "The Eulerian method you used for the particle system moves stuff from high density to low density cells, right? Could the Eulerian method be used the other way, e.g. to make something that has gravity and pulls low density stuff towards itself? Also, I wondered if Eulerian simulation could be used for AI systems: maybe having different characters being attracted to or "repelled" by crowds." "3925": "Isn't abuse of text in a game a bad game design idea?" "3955": "Will you use correct typography terminology for the code or will you be carefree about it?" "3981": "By adding more and more layers of complexity to the engine, do you start to measure and optimize those parts just when FPS is low enough, or when do you usually start with optimization?" "4124": "What do you think is the hardest challenge for you in programming, these days?" "4457": "The worst part is, you say stuff about these tools being terrible and NOBODY SEEMS TO UNDERSTAND THEY ARE TERRIBLE. Everyone is like, "what do you mean???"" "4570": "Have you considered signed distance fields for text rendering?" "4640": "But don't you think you're not being completely fair to the other crowd, who are not going to lower level? For example, I love and care about lower level stuff, but to pay my bills I have to be able to output an application within 10th of the time it would take me if I did everything at lower level. I have no choice but to rely on WPF and C#" "4745": "It's not enough to see a good tool once to understand that modern tools are bad. I feel like you also need to be a pretty good programmer, which is far from where most of us are now. If you are a mediocre programmer, you won't feel it. Do you agree?" "4868": "Would you take a job in the mafia if they gave you a perfect version of Emacs and Visual Studio?" "4892": "Close it down" --- name: "day163" title: "Asset Processing with STB TrueType" markers: "2": "We can use libraries inside the asset processor" "50": "Two ways of generating the font bitmaps: Resorting to windows or using a library" "92": "Deciding to resort to an stb library" "218": "The stb libraries" "308": "The stb_truetype library" "337": "Structure of the stb libraries" "537": "Using the library" "579": "Library integration in two lines" "728": "Documentation of stb libraries" "831": "Rasterizing one letter" "991": "Pass the entire thing to Sean" "1107": "Using GetCodepointBitmap" "1167": "Font scaling; points and pixels" "1297": "Recording the size of returned bitmap and the X and Y displacement offsets" "1421": "Freeing the memory allocated by stb_truetype" "1470": "Appreciating work well done" "1543": "Using the character bitmap as a loaded_bitmap" "1849": "Displaying the bitmap" "1886": "Testing it" "1920": "Checking MakeNothingsTest" "2118": "Debugging the drawing code" "2170": "MakeEmptyBitmap was out of date and missing some initialization code" "2220": "Testing it again" "2318": "Flipping the letter bitmap upside-down" "2398": "Moving this code to the asset builder" "2529": "Merge handmade_asset_type_id.h into handmade_file_formats.h" "2583": "Adding one bitmap per letter to the asset file" "2802": "Reload the entire font file and make Sean parse it" "2983": "Good job, Handmade Hero" "3074": "Adapting the font rasterizer test code to the asset system" "3200": "Adapting the asset system to the new asset type" "3457": "AddCharacterAsset" "3562": "Thank the compiler" "3598": "Go ahead and run our generator" "3618": "Try and debug the program in Visual Studio" "3649": "Let's try that again" "3678": "This machine is very old" "3757": "Try to change the heads to be fonts" "3783": "Filtering which letters spew out of the fountain" "4049": "Library success!" "4136": "Q&A" "4156": "The 'A' is the best match for the null terminator" "4193": "Until tonight, I thought there was a use case for CMake (which is that, if the user compiles the program, it finds libraries so that you don't need to know where they're installed). But now... it seems the STB way is the only reasonable default. I think I'm done with CMake for the foreseeable future" "4292": "External libraries, malloc/free, what's next, a java virtual machine?" "4331": "You have used a library, and there are riots raging in the streets. I see shadows of pitchforks, cast by torch lights of the rabid crowd. Run, Casey, I'll do my best to slow them down. *tips his hat with a last farewell gaze*" "4366": "How would you write debug info now?" "4379": "Also, if you make the Hero spew out letters of my nickname at random (at least 'til the end of Q&A (and we already established that I'm the mascot of the community (le lovable goof))), holy hell will I be happy" "4400": "I noticed "mollyrocket" in one of the comments of the STB file... Did you make contributions?" "4423": "It looks like this episode was brought to us by the letter N" "4479": "Rephrase: how would you output sentences to see debug strings like fps or error codes?" "4496": "Is the debug text going to be spewing forth out of the handmade hero's head?" "4508": "I'm curious: what do you look at when hiring an artist (I have no idea how you apply for that)? After watching a few episodes of Double Fine Adventure I'm in awe at how good artists at Double Fine seem to be and what kind of *richnesses* you have to have to be one of those. You also seem to practise more intelligent and humane approaches to hiring" "4609": "It's almost 1am, please tell me this won't be a normal thing" "4689": "Can you input a tilde sign in emacs with your config, because I can't?" "4709": "I don't look for a practical advice, just interested how you do it now. Often my friends tell me "I can't give you an objective answer/data" "screw it, I want YOUR opinion!"" "4779": "ONE MORE! Ever thought of special episodes with guests/bonus episodes done on specific topics by someone else (being a rad debugger with Jeff or being a splendor deitial programmer with Fabian)?" "4830": "Is formatting coming tomorrow?" "4862": "I've heard you mention a "new language" someone is developing. Could you mention the name/creator? I Usually listen to Handmade Hero in my car on my way to work so I can't write it down if I hear it" "4916": "Go to bed" "5135": "See you on the internet, Casey" --- name: "day164" title: "Asset Processing with Windows Fonts" markers: "2": "Recap and plan for today" "103": "Reasons for and against using libraries in the asset processor" "259": "Windows calls to draw fonts" "371": "GetPixel: Simplest way of getting the rendered font, pixel by pixel" "426": "CreateCompatibleDC and CreateCompatibleBitmap" "526": "Defining an alternative code path inside LoadGlyphBitmap to render fonts via Windows calls" "591": "TextOut: Drawing text to an HDC" "681": "Creating the device context" "740": "CreateCompatibleBitmap" "840": "We are not using the right font yet" "863": "This is a zygote of a thing" "914": "Finding out space taken by the text" "958": "GetTextMetrics" "1008": "GetTextExtentPoint32" "1098": "Clearing the background prior to writing the glyph: Patblt" "1222": "SetTextColor" "1288": "Try doing some extraction" "1308": "GetPixel: Extraction of the glyph" "1430": "Recap of previous steps" "1524": "Test out this alternative font implementation" "1557": "Debugging it" "1610": "No need to debug; Casey remembers the cause of the problem" "1656": "SetBkmode: Setting the background filling behavior" "1709": "Selecting a background brush instead of calling PatBlt" "1758": "'Doopity Doo' by Casey Muratori" "1795": "SetDCBrushColor" "1828": "Let's test it" "1895": "Setting the background color with SetBkColor" "1933": "Success!" "1970": "CreateFont: Picking the font" "2071": "AddFontResourceEx: Making the font visible to windows" "2246": "We need to specify the font name" "2692": "We also need to mark the font as active" "2744": "Testing the renderer with a more recognizable font" "2814": "Back to STB font rendering for a minute" "2872": "Resorting to solid alpha to inspect the bounding boxes" "3174": "Scanning the bitmap to get the bounding box of the glyph manually" "3461": "Adding a one-pixel empty border" "3580": "Q&A" "3619": "Can the fonts have outlines?" "3643": "What did you mean by "backing bitmap"?" "3796": "I love how stb_truetype is easier and arguably better than the windows api version" "3804": "Vote on the strawpoll!" "3883": "Does windows font have subscript and superscript support and therefore so much overbounding? Also, is the anti-alias only stored in the alpha value by windows? After seeing a pro like you struggle with this API I understand the burden you go through with it, having seen STB yesterday" "3970": "To clarify, do we have the ability to create font bitmaps with outlines on the characters that could maybe be colored separately?" "4042": "Which one is worse: GDI or DirectInput8?" "4054": "Is today a good example of why sometimes using a library is okay?" "4211": "Would DirectWrite (or ClearType) help out with the anti-aliasing?" "4225": "Ignore this if you're already doing this, but why not ship the mono bitmap as part of the asset file instead of the much larger RGBA bitmap?" "4316": "Q: People are liking the idea of handmade.dev" "4355": "How often do you regret using a API/lib and back-up writing your own implementation? When you are fast-paced as you maybe this sometimes is better when your knowledge of the problem is sufficient" "4469": "What GUI toolkit do you recommend?" "4512": "Would CLEARTYPE_QUALITY instead of ANTIALIASED_QUALITY make a difference?" "4530": "Blackboard: LCD pixel elements" "4632": "That's all she wrote" --- name: "day165" title: "Fixing an Asset System Thread Bug" markers: "50": "Two possible plans for today:" "61": "a) Construction of sentences and paragraphs" "129": "b) Fixing a bug. Let's fix the bug" "223": "Explanation of the bug" "358": "How does the bug happen and how should we fix it?" "473": "One approach: Marking assets as used or not used" "509": "Cons of asset locking" "574": "Blackboard brainstorming" "604": "In-flight asset protection" "673": "Usage patterns of assets" "801": "Keeping an asset usage count and its associated problems" "965": "Introducing render_group generation IDs" "1202": "Cons of this approach: Possible wrapping of the IDs" "1304": "Maybe the wrapping is not a problem, after all" "1394": "Some other complications of this approach" "1634": "Feasibility of using generation IDs given the current state of our asset system code" "1845": "Generation IDs make MoveHeaderToFront superfluous" "1920": "Doubly-linked lists and threading don't play well" "2158": "Blackboard explanation of some problems we will encounter" "2249": "One possible solution: Queuing our MoveHeaderToFronts so that only one thread performs them" "2342": "Another solution: Lock-free heap data structure" "2399": "Yet another idea... that also poses some problems" "2568": "We could also sort the generation ID-asset pairs separately" "2780": "How about a multithreaded heap?" "2902": "Coding the "generation IDs" approach" "3328": "Updating the GenerationID" "3444": "Compressing GetBitmap and GetSound together" "3710": "Leaving the code in a working state (although we are still not finished)" "3837": "Q&A" "3892": "Hey Casey, can you do a 2-min recap of everything done today?" "4069": "How often do you actually implement something from a paper?" "4125": "What would be the worst case scenario if you had multiple threads trying to remove an asset? Couldn't you just wait till no thread was trying to remove the asset?" "4154": "One way to avoid the lock is to split the LRU list into two parts. Keep the most recent 25% of it in one partition and the least recent 75% in another. Only move an asset to the head of the list if it's in the least recent part" "4194": "So IIUC, our problem is that "least recently used", in this context, means "least-recently-stopped-being-used-in-all-threads", and we can't really know that for certain without having some form of inter-thread communication.... Is that correct?" "4243": "Meathead protein-powder action" "4398": "You don't take the lock on hot assets most of the time" "4454": "I haven't seen you drink any milk this stream, is that why you are tired?!" "4496": "You can avoid the genid gap checking list by keeping min/max/cnt rendergroup "done" ids, and freeing all assets 0? Or will we now need to include the ASCII control chars to make CodePointCount work?" "4002": "Will you have stream later: On various meta programming tricks? Some useful & nifty tips and tricks for developers?" "4052": "Which Chinese dialect are you thinking of supporting?" "4115": "How big do you think the game will be in the end?" "4131": "How about right-to-left languages?" "4201": "We ended the questions right as the stream ended" --- name: "day171" title: "Adding Font Metadata to the Asset Builder" markers: "25": "Recap and plan for today" "294": "We want the ability to load multiple fonts" "380": "TODO(casey): Are there larger numbers than 4096...?" "426": "Using more explicit asset structs in the asset packer" "743": "Moving the font loading code to a separate function" "1040": "Freeing the memory taken by the fonts" "1105": "We need at least a font for the game and another one for debug purposes" "1141": "Our STB code path is broken for the moment" "1170": "Making fonts available as usable assets" "1216": "AddFontAsset" "1285": "Pulling together duplicated code into AddAsset" "1659": "Hardcoding the codepoint count until we know the range of characters we want to load" "1821": "Initializing the global font device context at startup" "2194": "Building the font tables" "2338": "Writing the asset font information into the asset file" "2501": "Faking the horizontal advance using the width of the current character" "2722": "Loading the font data from the asset file" "2745": "The codepoint loading gets tricky when using more than one asset file..." "3048": "...but we can do the codepoint rebasing per file!" "3455": "Q&A" "3485": "Give us a sec" "3505": "I tried to explain to someone that a color is just a uint32 and I am not sure I got it across" "3541": "Blackboard: "Color" -> Ambiguous term!" "3826": "You added Textmetrics into the struct and then decided to alloc it - why? And whats the benefit?" "3902": "About the language having different fonts. Would this apply to added packages by other people?" "3960": "I'm talking about in terms of how the GPU cares about the color of a pixel, as opposed to a struct with float r,g,b,a. Which is not really necessary for a buffer thing" "3982": "Blackboard: GPU ~ CPU" "4447": "Do any systems ever represent light as an actual frequency and change that value based on interaction with the simulated environment?" "4588": "If you take in user input at some point will you worry about blocking Unicode control characters?" "4604": "So you care about the stack memory. When would you start to really measure it, or is some gut feeling enough? I would never had that idea before not getting an actual error" "4635": "What is HDR?" "4731": "Do you think there will be a time when CPU and main bandwidth is fast enough to replace GPUs entirely, going back to the days of software renderers?" "4752": "Wind things down for dinner" --- name: "day172" title: "Extracting Kerning Tables from Windows" markers: "48": "Recap and plan for today" "163": "There's a bug that prevents the fonts from loading" "217": "Writing fonts in a separate asset file" "370": "Stepping through the asset packer" "773": "We were not setting the horizontal advance correctly. For the moment, we'll just hardcode it to be the width of the current character" "995": "We were using the incorrect AssetType for our font glyphs" "1130": "Testing and still not loading" "1141": "Stepping through the asset loading code" "1276": "Take it back" "1305": "On getting older" "1336": "Debugging LoadFont" "1363": "We were not calling LoadFont yet!" "1419": "Implementing PushFont" "1620": "The fonts are back!" "1697": "Let's look for the correct kerning pair values" "1786": "Reviewing the GetKerningPairs docs" "1870": "Figuring out the number of kerning pairs" "1929": "Getting the kerning pairs" "2000": "Structure of tagKERNINGPAIRs" "2163": "What is the default advance?" "2478": "Question the ABCs" "2493": "Checking the system header files to see which functions and struct offer wide-character alternatives" "2603": "Debugging the LoadFont crash" "2730": "GetCharABCWidthsW expects a range, not a count" "2760": "Our fonts look nicer now" "2826": "Using the ABC's A information to modify the alignment of our glyphs" "2893": "(Blackboard) Diagram of the alignment point calculation" "2972": "Our fonts look even better" "3073": "The fonts still look bad, but it's Windows' fault" "3148": "See how Segoe Condensed looks" "3186": "Windows fonts make a fontographer cry" "3267": "We still have to see how our glyph bounding box detection interacts with the system's kerning information" "3421": "The alignment based on the bounding boxes was already correct and we didn't need the ABCs" "3630": "Modifying the TextOutW call in the asset packer to allow Windows to paint glyphs to the left of the specified drawing point in the font Device Context" "3794": "Q&A" "3817": "Could you use another text sample like "AVA WA Ta"" "3862": "Learn something new about Arial and Helvetica" "3982": "How do you know so much about fonts?" "4046": "Do you typically license fonts for use in games? Or does the loophole about rendering them to bitmaps mean you can just use whatever you want?" "4068": "Recommend Google Fonts" "4226": "Is fonts a topic you enjoy? An author once wrote: "If music is the subjective application of physics, then font rasterisation is almost certainly the subjective application of computer science." Do you agree?" "4270": "Probably doesn't make sense to look at kerning for lowercase to Uppercase. I doubt many fonts bother with those cases" "4325": "Would Times New Roman be any better?" "4330": "What are some examples of font / typesetting systems that can do kerning well? Is Knuth's TeX the only game in town?" "4454": "Hmm... good point. More game designers should have a guy / gal who knows about fonts, because I see lots of games where it's hard to read quest text / chat text" "4518": "Regarding the abstract text, I agree! Which is why I asked. Given your experience, maybe you could've read more into that than I could" "4551": "The down-left corner of the "A" is cut, but you search bounds by the pixels, so why did this happen?" "4593": "Have you played Facade and / or met the designers?" "4689": "Clear everything to black instead of white" "4854": "You said Molly Rocket's upcoming game has crazy font functions - can you say one example what about fonts can be crazy? Just wondering" "4872": "What's behind the curtain?" "4884": "Facade was kinda interesting. One time I typoed the first thing I said to the guy when he opened the door and he just scowled, shut the door in my face and then the game faded to black and ended" "4906": "Check our edges" "4943": "Close things down here" --- name: "day173" title: "Precise Font Alignment" markers: "14": "Recap and plan for today" "106": "Review of last episode" "135": "The first line should start one line down from the top of the screen" "287": "We want to be able to access the LineAdvance information without having to load the font" "338": "The placement is not correct yet" "435": "The zero Y is at the center of the screen, not the edge" "459": "Testing multiple sizes inside a word" "534": "We don't have the necessary information to do kerning between characters of different sizes" "566": "(Blackboard) Explanation of the problem" "744": "Our Kerning tables don't specify the initial horizontal offset in the absence of a preceding glyph" "830": "Special-casing the kerning for the null glyph in the asset packer" "902": "Fix the variable shadowing" "913": "Still not lining up with the left edge and upper edges" "951": "Lining up with the top edge by looking at the ascenders and descenders of the font" "1311": "The characters still don't line up with the top edge, but it's because the font includes glyphs taller than the ones we are displaying" "1426": "Aligning the text with the left edge. Baking the leading space into the kerning" "1555": "Processing the characters before the fonts to have access to the necessary information" "1838": "Compare kerning" "1923": "The ABC's A was already included in the horizontal advance" "1985": "The kerning is still not quite right" "2025": "Using our own measurement of the width of the character instead of the ABC's B" "2146": "Debugging some more" "2449": "Checking the documentation of the ABCs" "2622": "(Blackboard) Thinking some more about the problem" "2704": "In order to be able to flush-align all characters to the left, the prestep of the current character should be applied to the next character!" "2865": "Subtracting our kerning adjustment from the previous character" "2985": "No kerning for characters following the null codepoint" "3057": "Is it even possible to match Windows' kerning exactly?" "3090": "We'll have to compress the font ranges to support kerning for other languages" "3351": "Q&A" "3421": "The more I see the kerning in Notepad, compared to yours, the more awful it looks to me" "3444": "I realise that this is uncharted territory, but it seems to me that font rendering is taking more time than the rest of the renderer. Is that normal?" "3629": "Isn't Japanese evenly spaced?" "3652": "Migraine :(. Glad to at least catch the Q&A" "3669": "I was testing kerning in Notepad, Word, Wordpad... No kerning there? Where do you have seen kerning in Windows?" "3686": "Don't forget the boilerplate" "3692": "John Carmack programmed low level graphics and got a Ferrari. Font rendering guy never got anything. When are we going to go back to programming cool superstar things?" "3764": "I'm in my second year at uni for programming, and I still have problems getting my head around single things. My question is how long did it take you to have a good understanding of programming in general?" "3791": "Fair enough. Maybe it just seems like progress is slower for some definition of "progress"" "3822": "I'm confused why the font rendering relies so much on windows. Isn't all this stuff stored in the font files, or is that harder without Windows text metrics and such? Or, to put it another way, how would what we did today be different if we were using stb_truetype?" "3858": "On the MSDN entry "Uniscribe Glossary" ABC Values is better explained how Windows understands it" "4020": "Ignore the documentation and just do GetCharWidth32" "4093": "See how that kerning looks" "4210": "Do you use the graphics card at all when rendering?" "4226": "I'm sure this has been answered so feel free to ignore if true. What are the features of C++ that you use that keep you from using just plain old C?" "4252": "When you say Windows uses kerning, why is every letter never overlapping in the space of the followed letter? In your code I see the letters overlapping. Did I understand kerning wrong?" "4296": "O-oh yeah, well, John Carmack also got to make Rocketships, so he wins" "4323": "Are you saying Adobe has better programmers than Id?" "4381": "Why didn't we use bitmap fonts and used TTF? Bitmap fonts are cross platform, are they not?" "4416": "When I render on a GPU, is there a way without copying the render result back to RAM?" "4444": "Japanese isn't evenly spaced. Some characters like 「 and 」 rely on kerning" "4497": "How do you render to the GPU?" "4527": "Favorite font for reading?" "4544": "To display the result" "4594": "I almost got a headache when you said alignment is not the same as kerning, please expound" "4611": "Blackboard: Spacing vs. Kerning" "4814": "Would you rather have a CPU with more cores than a GPU, or enough clock cycles to outperform the GPU with software rendering?" "4832": "You can look here, 3. Tsumegumi for Japanese kerning" "4943": "When thinking Adobe has a market value of over 40billion, why no great programmer wants to do a better Photoshop?" "5080": "There are actually a lot of people competing with Photoshop, and you are using one of those products on stream right now..." "5161": "Wind it down" --- name: "day174" title: "Adding Sparse Unicode Support" markers: "15": "Recap and plan for the day" "108": "Spaces are not displayed" "170": "Adding the kerning value for space to the kerning table" "245": "But wait... that kerning value was already there" "291": "Explanation of Casey's previous assumption of what caused the bug" "354": "Debugging the asset packer" "386": "It seems that the asset packer does not process the space codepoint" "465": "The asset packer ignores the space glyph because it has no visible pixels" "497": "Spaces are back but we have lost the small letters" "498": "Run Handmade Hero, although..." "530": "Fixing a bug introduced while fixing the problem of the visibility of the space glyphs" "578": "Checking the width of rendered spaces" "617": "Choosing a target foreign string to test the rendering of non-ASCII characters" "681": "Checking that Arial has all the necessary codepoints" "731": "Finding the codepoints associated to the test string" "892": "A table that encompassed the complete range of characters necessary to represent both ASCII and our target kanji would be massive" "970": "We need a way of condensing the ranges of available characters" "1003": "(Blackboard) Layout of the 1-D symbol lookup table" "1091": "Easiest but slow solution: store the codepoints themselves for each row of the table" "1162": "What about preprocessing every string to store the indices to the glyph tables instead of the characters?" "1322": "Or we can simply store one big table that maps each character to its associated glyph index" "1383": "Any objections?" "1407": "Storing pairs of codepoints and bitmap_ids instead of just bitmap_ids" "1480": "The new codepoint table will be decompressed at runtime and used as a direct lookup table" "1531": "Let's implement that" "1850": "Adding the kanji owl characters by hand to the asset file" "1880": "Do AddCharacterAsset for the Kanji Owl straight after adding the other font Assets" "1934": "Modifying the code that uses plain characters to use glyph indices instead" "1962": "Setting a maximum glyph count" "2227": "Fonts are done" "2282": "Using a huge table at asset pack time to map every Unicode codepoint to our glyphs" "2605": "Freeing memory associated to the loaded_font variables" "2639": "Propagating the last changes through the code" "2691": "We can't refer to the kerning of a pair of glyphs until we have mapped both glyphs" "2958": "Modifying the HorizontalAdvance table as the last step before writing the font to the asset file" "3121": "(Blackboard) Writing only the part of the HorizontalAdvance table that we'll use" "3184": "Starting to implement the partial storage of the HorizontalAdvance table" "3372": "On freeing things" "3381": "Leaving the code in a compiling state before the end of the stream" "3547": "Q&A" "3566": "I noticed that you rarely comment your code. Your comments mostly consist of TODO comments. What are your thoughts on commenting your code, considering a lot of it is pretty complicated, unless of course you don't see it as such? Or do you think that since you write good code, it doesn't require comments to be readable?" "3719": "Why was your first calculation of the GlyphTable index size too big (64k) and reduced to 2k, and still later went full-on 64k again? What changed the size?" "3774": "Would it be a good practice to comment after writing all your code for others?" "3957": "Since the questions are slow today, when do you think you will write a proper RNG?" "3973": "Or a real hash function?" "4026": "My comment-writing rule for a while has been: "code should clearly tell you what is being done; comments, if you need them, should only tell you why"" "4075": "How long have you been coding (years)?" "4083": "When will you implement the chocolate wine fountain?" "4119": "Call it" --- name: "day175" title: "Finishing Sparse Unicode Support" markers: "23": "Recap and plan for today" "70": "Reviewing the the current status of the test asset builder" "295": "On type-safe memory allocations" "433": "Reserving space for the null glyph" "639": "Happy Birthday, Windows" "798": "Running the asset builder" "830": "Reviewing the asset loading code" "870": "We don't address Unicode codepoints directly anymore" "916": "Unpacking the dense glyph table" "978": "Using an unnecessarily big Unicode mapping table for the moment" "1193": "Storing the highest used codepoint in the asset file" "1345": "Hunt for ONE_PAST_MAX_FONT_CODEPOINT" "1383": "Genius day at Handmade Hero" "1406": "Casey's mommy says he's very good at programming" "1479": "We normally wouldn't be doing finicky suballocations by hand" "1580": "Adding extra finalization code after font loading" "1690": "Building the Unicode mapping table" "1970": "Implementing ZeroArray helper function" "2050": "Guarding against overflows by double casting" "2127": "Substituting codepoints with glyphs" "2245": "Implementing the glyph lookup routine" "2306": "Debugging today's and yesterday's changes" "2334": "No fonts visible. Let's inspect the font loading code" "2373": "OnePastHighestCodepoint was set but not saved to the asset file" "2558": "Another small error in font loading code" "2600": "Our font is back!" "2608": "Displaying the handmade owl unicode codepoints" "2648": "We egged Casey on" "3070": "The kanji codepoints are there but not kerned properly" "3140": "Q&A" "3219": "So, are we done with fonts now? Moving on to other parts of the debug?" "3272": "So what will we be moving onto next week?" "3313": "Any chance you could use a different font for the editor? Hard to tell difference between 0s and 8s" "3334": "It's possible that that's how it is supposed to be kerned" "3417": "Maybe it's just twitch, but the letters in Red look a bit off on the edges" "3578": "Might be a basic question but why do we need our own font rendering? Doesn't Windows have its own font rendering functions we could call?" "3674": "I saw you were wearing something around your forearms. Is that to treat Tendinitis? I heard about this condition from typing too much" "3687": "People don't understand why a font rendering system can be complex because they think in terms of pixels. Any comments on this (only if there are no other questions)?" "3719": "Can you check if your numbers are monospaced? For example, 111111 should be the same width as 999999" "3797": "What happened to ZoomIt?" "3861": "Not a question but I think ZoomIt is just on the desktop" "3948": "The ones and nines don't line up the same way in game and in notepad" "4017": "How do you have the background black in Mischief? I found it a bit tricky to change the background color for some reason, surprisingly!" "4037": "How do you prefer to traverse trees, loops or recursion? Why?" "4066": "If you want to start your own game project, do you start from scratch, use Frameworks / API / SDKs (SFML, SDL, etc.) or use an engine (custom made by you, or one that already exists)?" "4121": "They don't line up relative to each other though" "4165": "Any plans to add scripting or modding hooks?" "4193": "Off-topic: How do you grep with your Emacs config?" "4241": "Sure. Some (reasonably) think of the screen as a grid of pixels and that font rendering is directly plastering that font on the screen. So nvm, they just haven't understood beyond bitmap fonts" "4306": "What font do you use in Emacs?" "4339": "Why did you use GlyphIndexFromCodePoint instead of an array of (mostly null) pointers to achieve sparseness?" "4398": "How valuable do you think non-mono-spaced fonts would be in, say, an editor?" "4450": "Could you recommend a website or YouTuber that could teach me coding? I really want to learn" "4605": "I like to limit the scope of my functions to be defined only where they're used. How do you workaround the fact that C doesn't have locally defined functions? Do you use functors?" "4668": "Vertical cursor navigation is easier to follow in a mono font" "4685": "Tried to use grep in Emacs: the program crashed" "4706": "How do you handle introspection / metadata to build your editor inspection tools?" "4745": "Wind it down" --- name: "day176" title: "Introduction to Debug Infrastructure" markers: "67": "Plan for today" "154": "Test-driven development doesn't help solving the harder problems of game programming" "299": "Purpose of debug services" "393": "1) Coaxing bugs to the surface" "480": "2) Locating bugs that are clearly present but difficult to pinpoint" "718": "We'll focus on versatile debug services aimed at solving difficult bugs" "801": "Logs. Example of debugging framerate problems" "949": "We could start by recording our debug timers on each frame" "995": "Simplifying the usage of our debug timers" "1058": "We could combine the log and the looped live code editing replay system" "1201": "Limitations of this approach - Is not particularly good for multithreading problems" "1283": "Necessary components: counter log, replay system, log of memory consumption and diagramming" "1336": "Diagramming" "1557": "We want all the debugging subsystems going through the same log" "1634": "We want to avoid having to change the code in order to debug it..." "1751": "...and also avoid having to remove debug calls once we're done" "1904": "Review of desired features for our debug system" "1976": "Will we need tuning/fiddling support?" "2200": "Let's start building the debug system" "2285": "The old debug cycle counters were lousy on purpose" "2580": "Improving the interface of the cycle counters" "2607": "Abusing constructor/destructor pairs to achieve that better interface" "3289": "We shouldn't need to store values anywhere to make paired calls at the beginning and end of a frame" "3431": ""I just kind of ruined The Variable"" "3663": "Review of the inner workings of the new cycle counter interface" "3735": "Testing that the code still runs after today's changes" "3757": "Q&A" "3802": "Is there a way to determine how much overhead the debug takes when it is enabled? (Or is there such a thing as debug levels?)" "3888": "Why not use a simple template? That would remove storing the ID, e.g. template struct timed_block {};" "3950": "Would you agree that there is a similarity between test driven development and "writing the usage code first"?" "3992": "Would you consider functional programming for game development?" "4081": "How does the StartCycleCount get stored in the struct when you don't explicitly set StartCycleCount = StartCycleCountInit or something what you did with the ID?" "4135": "Do you get Heisenbugs, where the bug happens only when there's not any debug code running?" "4218": "So the destructor gets called right when it goes out of scope?" "4448": "Community fight" "4465": "Close this down and wrap up another episode of Handmade Hero" --- name: "day177" title: "Automatic Performance Counters" markers: "11": "Plan for today" "100": "Recap of work done in the previous episode" "221": "TIMED_BLOCK should be easier to use" "309": "Timing a block should be an inexpensive operation" "423": "Don't be afraid of major changes" "467": "Getting rid of the debug counter IDs" "505": "Preprocessor directives" "667": "The __COUNTER__ preprocessor directive" "707": "Consider MSVC's gender" "768": "Preprocessor directives are frequently used in debug code" "802": "Getting rid of the argument to TIMED_BLOCK" "876": "Avoiding predefined values while still describing the location of the TIMED_BLOCK call" "1009": "Mapping filenames and line numbers to IDs" "1044": "We could use some sort of mapping strategy, but that's too complex for a debug log system" "1154": "An alternative method: Avoid looking for filenames and line numbers until we need to print them" "1247": "Depending on the amount of information we log, this method could tax our write bandwidth" "1426": "We'll try first the alternative method" "1488": "Have a thought" "1491": "We could resort to __COUNTER__ because of our single compilation unit build!" "1547": ""Are you thinking what I'm thinking?"" "1590": "Quick test of the __COUNTER__ approach" "1765": "__COUNTER__ passes the test!" "1796": "Dealing with two translation units. We will keep one array of debug records for each of them" "1904": "We could define the DEBUG_PREFIX preprocessor symbol to access the proper array" "2002": "Forward-declaring the debug record arrays" "2096": "Accessing debug records" "2166": "Using the DebugRecordArray preprocessor symbol instead of DEBUG_PREFIX" "2280": "Defining the fields of the debug record array" "2313": "Implementing the timed_block constructor and destructor" "2432": "Using the new TIMED_BLOCK syntax" "2568": "Adding HitCount as an extra parameter to TIMED_BLOCK" "2696": "handmade_debug.h: Fuss with the vagaries of C++ preprocessor nonsense" "2700": "Expanding __LINE__ in the presence of the paste operator" "2908": "Modifying OverlayCycleCounters to work with the debug record arrays" "3041": "Testing today's changes" "3060": "Identifying our debug counters using the file names stored in the debug arrays" "3100": "It works!" "3129": "What we have accomplished today" "3188": "Q&A" "3256": "There's an alternative way to start / end the counter instead of using constructor / destructor pair, and you don't have to store the data in the struct. Maybe not as convenient but it's worth mentioning. I use it quite often when I have to 'begin X' -- write code -- 'end X'. It's basically a hacked / tweaked version of C#'s 'using' statement. I think you'll find it interesting" "3313": "Write out elxenoaizd's suggestion" "3393": "I feel like I missed something: why does the array name need to be different between builds?" "3440": "How do you move your typing cursor around so fast? Is that an IDE-specific macro?" "3487": "Could you expand on how you would have done the char *Filename / *FunctionName with uints instead?" "3554": "This is awesome. You have a few minutes left: could you output the results or show them in the debugger?" "3574": "handmade.cpp: Print out the debug cycle counts" "3874": "Do you recommend taking game-programming as a major or programming in general?" "3888": "What other useful preproc values could we use other than __FILE__, __FUNCTION__ and __LINE__?" "3947": "I'm not sure I fully understand Unity builds. So Unity build is when we compile everything to a single file? I don't think that's the case because we do have multiple source files in HMH..." "4036": "Where did the whole weird IInterface CClass style of programming I see everywhere come from?" "4063": "Why do you have both u32 and uint32 typedefs? What's the difference?" "4098": "If exceptions are bad, then what is a good way to handle errors? Just return error codes? A global error value like in errno or GetLastError()? What do you think of the idea of having a central error handling function that we call and pass it the error id and it acts accordingly (switch statement maybe)?" "4239": "Why use Record->FileName instead of Record->FunctionName?" "4247": "I am kind of new to the stream. Is there a reason you hate C++ so much?" "4334": "Will this game compile with gcc or only with the Visual Studio compiler?" "4384": "General Programming Question: Do you see the use of public variables being accessed outside the class bad practice, versus using a "getter / accessor" function?" "4443": "handmade.cpp: Demo bad programming practice" "4592": "How would you handle parsing errors / exceptions in a recursive decent parser?" "4608": "Internet says __COUNTER__ started on VC++" "4673": "Spin it down" --- name: "day178" title: "Thread-safe Performance Counters" markers: "16": "Recap and plan for today" "147": "Packing a tiny monospaced font into the asset file" "245": "Supporting font selection" "414": "Adding the debug font" "549": "Testing the packing of multiple fonts" "608": "The AssetCount is wrong. Let's debug that" "710": "We're missing one entire character set" "885": "Are TypeIDs not initialized?" "922": "Let's see if it's the asset processor's fault" "1056": "The way the code is structured, we can't BeginAssetType twice for the same AssetType..." "1093": "... but we can group all the font packing calls inside WriteFonts to sidestep that issue" "1156": "Tagging the fonts" "1325": "Testing the new font packing" "1360": "Picking a different font" "1435": "It works!" "1473": "Specifying the size of the font" "1650": "Adding some extra TIMED_BLOCK calls" "1919": "There are still two problems that we need to solve:" "1922": "1) The timing of anything that encloses the render process is wrong" "1960": "2) The access to the timers is not thread-safe" "2100": "The first problem can be solved by displaying the counters with one frame of delay..." "2180": "... but we'll first solve the threading problem" "2202": "(Blackboard) Thread-safe performance counters" "2215": "Review of implementation of performance counters. Using Record->CycleCount as temporary storage is problematic, because it should contain the end result" "2360": "Using a separate value to keep track of the StartCycles" "2415": "The concurrent access to HitCount and CycleCount is also a problem" "2548": "Implementing AtomicAddU32" "2655": "Consulting the _InterlockedExchangeAdd docs" "2756": "The result does not look correct yet" "2780": "Resetting the counters atomically" "2864": "Correcting the _snprintf_s format specifiers of the time counters" "2890": "Updating CycleCount and HitCount atomically together by merging them into a single U64" "3152": "Making the reading and resetting of the counters also atomic using an unconditional atomic exchange" "3236": "It seems to be working" "3245": "We are now thread-safe" "3320": "Reporting both DebugRecordsMain and DebugRecordsOptimized" "3528": "Reporting also the line number of TIMED_BLOCKs" "3585": "Adding some more TIMED_BLOCKs" "3630": "The path of least resistance should be the right path, so that doing the right thing is never drudge work" "3670": "Q&A" "3696": "This was, again, pretty awesome! Thank you" "3704": "Wouldn't a union be helpful for that HitCount_CycleCount? It just seems unnecessary having to remember their offsets and / or lengths" "3734": "Yesterday I asked about preprocessor constants other than __FILE__, __LINE__ etc. I did some searching and found out about __TIME__ and __DATE__. Maybe it's useful for us to include a date-time stamp in some of our logs?" "3770": "Can you align the text into columns with %32s in the sprintf or something?" "3789": "handmade.cpp: Align the text into columns" "3865": "You mentioned yesterday that destructors are called when the scope of the object ends. I just wanted to note it seems that if you use it to exit a function instead of 'return' then the destructors won't get called!" "3898": "Will you marry me?" "3927": "Won't rtdsc give wrong results if your thread is pre-empted and scheduled onto a different CPU between the constructor and destructor calls?" "4098": "Are you working on any games other than Handmade Hero?" "4117": "General Programming Question: Do you have any general advice for optimizing code performance, e.g. multithreading, algorithm complexity analysis, etc.)?" "4140": "Sorry I made a typo in the previous question: You mentioned yesterday that destructors are called when the scope of the object ends. I just wanted to note it seems that if you use "exit" to exit a function instead of 'return' then the destructors won't get called!" "4184": "The values are pretty hard to read when they're changing literally every frame. Wouldn't it be better to average them?" "4211": "Have you considered keeping the timers in thread-local storage instead of using atomics every time you write to them?" "4331": "Are lock-free data structures worth the time they take to write?" "4355": "Do you think it would be worthwhile to make the time records hierarchical (like a call tree), and how would you go about it?" "4483": "Can you explain the difference between mutexes and interlocks?" "4517": "Blackboard: Interlocks and Mutexes" "4843": "Wait, about the values, can you draw a graph out of them?" "4855": "NOOO! Save the Cherry MX Blues" "4863": "Will you be able to fix the click bug at the end of sounds with the debug system?" "4896": "Can you still time a smaller section inside the code or does it just work for whole functions now?" "4941": "I noticed you prefer to keep things on the stack and return by value. 0) This helps with locality of reference and is more cache friendly, am I right? 1) Is the stack size something to be concerned about? 2) When returning by value, is the time taken to copy the object and return it something to be worried about? Maybe when the struct is large? In that case, do you prefer to return a pointer to the object?" "4986": "How do threads wait on lock-free structures? Do they?" "5300": "What's wrong with pointers to inline functions?" "5339": "Why you skips my questions?" "5349": "Did you get a degree in CS? What's your background on programming?" "5382": "Wind it down" --- name: "day179" title: "Tracking Debug Information Over Time" markers: "43": "Rant: Dedicate this episode to an awful company" "341": "Boot this up on maybe the last version of Windows which works in terms of rendering fonts" "390": "Apologise to those following along at home on Windows 8" "427": "Our debug timer system is still missing some important functionality:" "446": "1) The timings are hard to visualize" "513": "2) It lacks the ability to point out which code is responsible for missed frames or other performance issues" "632": "We want to keep a longer history of the values of our performance counters" "742": "We are interested in keeping track of events that happen in the platform-specific layer, so some part of the debug system will have to live there" "849": "The platform layer will announce the end of each frame to the debug system" "1054": "The platform layer will also inform the debug system of several other events" "2121": "Writing the plumbing around DEBUGGameFrameEnd" "2220": "Allocating debug memory on the platform layer" "2307": "Improvising the set of structs that will keep track of the values of our counters" "2460": "Modifying OverlayCycleCounters to use the debug memory" "2614": "Making DEBUGGameFrameEnd update the debug records" "2810": "Allocating some memory for the debug storage" "2901": "The debug information is now piped through the new system" "2918": "Recording the snapshots into a rolling buffer" "3027": "Recording the minimum, maximum and average values of timers" "3343": "Using double precision for the values of timers" "3483": "Printing out the statistics" "3529": "The output looks incorrect because we're not using the appropriate type specifier for the timers in _snprintf_s" "3583": "(Blackboard) Deriving the correct expression for the average cycles/hit. (Although it should be hits/cycle; see Q at 1:07:29)" "3944": "Q&A" "3975": "Song: 'Questions For Me' by Casey Muratori" "3985": "Is a C compiler faster in compiling C code than a C++ compiler compiling C-like C++?" "4043": "Shouldn't it be CycleOverHit?" "4049": "handmade.cpp: Change HitOverCycle to CycleOverHit" "4063": "Is there a standard / portable way in C to get a FILE* to a block / region in memory? In Linux there's fmemopen but I can't seem to find an equivalent in Windows. Internet seems to suggest MapViewOfFile but I don't think that is it, I don't want a memory mapped file, just FILE* to a memory region. Does such a thing exist or am I looking at this the wrong way?" "4156": "Are there inherent problems with using composition for writing game engines like there are problems with OOP?" "4178": "Why is the preprocessor able to convert a parameter to a string via the # symbol, but not the other way around, i.e. string stripping, taking the inner value of the string and pasting it? My guess is that it's because this would not make it possible for the macro to be determined at compile time since we can pass it arbitrary strings?" "4264": "Unless I missed it, shouldn't it be CycleOverHit rather than HitOverCycle?" "4274": "Averages of averages need to be weighted by the population size. This is a common mistake that you even see in scientific papers that try to combine the results of other scientific papers" "4327": "Turbo C's successor is C++ Builder from Embarcadero" "4349": "Metaprogramming question: Let's say I want to have a generic dynamic list (resizable array) in my game library. Void-pointers and macros are two ways of approaching this; another is generating the code for the unique list types I want. Is this what you mean when you say "I write C programs that spit out C programs"? If so, can we do this generation at compile-time (like we can do in jai) or are we forced to write and run an executable that does the generation for us?" "4409": "With respect to composition: I have a Player struct that has various other structs to represent what the player is composed of. One could be the Object struct which is added to any entity in the game that I want to behave like an object. Then I create functions that run on objects such as objectMove(Object *obj) so that anything that I want to move in the game would simply have an Object struct within it" "4469": "When writing game engines, how much should a programmer know about how the compiler works, and what is a good way to learn what is going on under the hood?" "4549": "Hey! I am looking to pick up programming, I have some basic knowledge but really would like to know where to get started and any suggested languages you might think are a good place to start" "4594": "How much more engine work are we going to do before diving into gameplay stuff?" "4695": "Can you run around in the game a little bit? The last time I watched was a month or two ago and I'd love to see how it's progressed" "4781": "Your thoughts on using a scripting language with the game engine?" "4804": "For the performance counters, could you perhaps color-code them according to how far outside of an ideal or expected range they are? Similarly is there a way to (roughly) estimate the ideal cycle count of a function?" "4846": "I have an interview tomorrow and I'm going to have to whiteboard. How to not be nervous?" "5154": "That's about it for today" --- name: "day180" title: "Adding Debug Graphs" markers: "11": "We will replace the C standard library functions at some point" "165": "Recap" "246": "Let's display the debug information in a more useful way" "290": "Moving the debug code into handmade_debug.cpp" "485": "Graphing the values of timers" "524": "Displaying also the counters that have not been updated in the last frame" "613": "We will pick the maximum value of a timer over a period of time and use it to scale its plot" "754": "Drawing a rectangle for each counter" "872": "Plotting the rectangles next to the text, aligned to its baseline" "956": "Using the ascender height of the text as the chart height" "984": "The debug display code needs simpler access to font information" "1058": "Using the relative value of the timer with respect to its maximum value to modulate the color of the rectangle" "1209": "Testing the code so far. Our heartbeat graph doesn't line up with the text" "1256": "Centering the timer plots with respect to the text" "1306": "The automatic change of scale of the timer plots is not perfect, but there's no immediate way to solve it" "1434": "Adjusting the plot sizes" "1551": "Some of the performance counters are never hit and they show as "null". We won't be drawing those" "1678": "We will save the platform layer debug_frame_end_info timings also as snapshots and we will display them as a stacked graph" "1770": "Moving the DEBUGGameFrameEnd function to handmade_debug.cpp" "1948": "Capturing debug_frame_end_info snapshots" "2035": "The order of the debug_frame_end_info fields is specific to the platform layer and it shouldn't be" "2097": "Transforming the individual debug_frame_end_info counters into an array of self-describing debug_frame_timestamps" "2221": "Now we can iterate over all platform timestamps and plot them as a set of stacked bars" "2330": "Using the inverse of our framerate (33 ms) as chart height" "2752": "Implementing RecordTimeStamp" "3030": "Testing the stacked bar chart. It's not positioned correctly" "3160": "The plot seems to be overshooting 33 ms. Let's draw a reference line to check that" "3256": "Yes, we're missing the target framerate" "3293": "Color-coding the stacked rectangles to tell them apart more easily" "3430": "Testing the color-coded rectangles. The plot doesn't look right" "3473": "We never bothered to stack the rectangles!" "3509": "It works now and the majority of the time is spent inside the GameUpdateAndRender function" "3592": "Q&A" "3701": "Doesn't the multi-core rendering screw up your timing?" "3757": "Can you briefly explain how it tracks how long it takes the frame to work and the render engine to work if rendering the debug is part of that work? Also a suggestion, use a key to toggle the debug display to see the game" "3952": "Did you get 4coder set up?" "3977": "Do you ever think it's amazing how 100s of designers can screw up a project by trying to be complex when indie designers can make a better game in a few months?" "4178": "You mentioned that the way you draw rects is not optimized. What do you want to change?" "4244": "Because you're using rendering on multiple threads, is it saying that you're spending more cycles in DrawRectangle / DrawRectangleQuickly than GameUpdateAndRender?" "4346": "Why are you echoing to lock.tmp in your bat file?" "4453": "So after "lib freedom week" we could reasonably easily boot HH off something like baremetalOS and go all "look 'ma no OS" (minus sound I guess)?" "4500": "Will HH be optimized for GPUs or are you sticking to CPU render? Will that be an arduous task or pretty straight forward?" "4532": "If I have a simple app concept that I can't code myself because I'm a scrub, is there any good way to get somebody to make an app for me that is somewhat simplistic and we split profits or even I just get 10%? I don't care about the profits I just want to help develop the app" "4572": "Why are you not using visual studio to write your code? It seems to be a windows machine you are working on" "4611": "Close outta here" "4645": "Announcement: GitHub private repository now available for those who preorder the source" --- name: "day181" title: "Log-based Performance Counters" markers: "11": "Recap and plan for today" "130": "Our performance counters are inexpensive, convenient and thread-safe" "219": "They report the amount of time an operation takes, but not _when_ it happens" "258": "In order to improve our profile view, we need to collect more data" "362": "The action of collecting the data should be cheap. Any real work should be deferred till the end of the frame" "456": "A log-based system could fit our requirements" "498": "Is the amount of logged events going to be too large?" "627": "Let's give the log-based approach a try" "655": "Can we call rdtscp?" "735": "We seem to be in luck" "830": "rdtsc tells us about elapsed processor time" "891": "rdtscp should also report which processor/core is running our code" "1140": "Trying to see if rdtscp returns the core identity" "1220": "We don't have a way of disambiguating threads at the moment" "1258": ""It's kinda nice to get stuff for free"" "1273": "We'll use a lighter version of debug_record to record debug entries" "1402": "Disambiguating threads, cores, debug_records and debug_record_arrays inside debug_event" "1459": "We only need a single big DebugEventArray" "1526": "Keeping track of the position inside the debug event array" "1555": "Double-buffering the debug event arrays" "1632": "Filling in the debug event records" "1702": "The array index will be determined by a preprocessor symbol defined inside build.bat" "1789": "Defining AtomicAddU32" "1954": "Telling apart the beginning and end of a timed block using entry types" "2026": "Pulling together duplicated event recording code into the RecordDebugEvent macro" "2250": "What is the 32-bit interlocked add-exchange instruction? It's _InterlockedExchangeAdd" "2438": "We can't do a synchronous exchange of pointers and clear the event index at the same time..." "2528": "... unless we pack the position and the event index together into a single 64-bit variable" "2741": "Exchanging debug event arrays at the end of the frame" "2790": "Transforming the macros into inline functions temporarily for easy stepping" "2860": "Our debug array is not large enough for the amount of entries we're recording" "2944": "Bump that number temporarily just to see if that really is happening for reals" "2970": "The information we log will allow more in-depth profiling operations" "3005": "Recap on the bundling together of array and event indices" "3049": "Switching event array indices correctly" "3209": "CollateRecords() can reproduce the behavior of our old non-log-based event system" "3432": "We have two event arrays (one for each compilation unit) and that makes the code uglier than it would be if we had better tools" "3505": "Linearizing the access to the debug_record arrays" "3741": "Fixing compilation errors" "3839": "Accessing the filenames, function names and line numbers of debug_records" "4010": "The log-based system seems to be working" "4057": "Q&A" "4084": "You mentioned that you use a known base address for your memory management. Could you talk a bit more about that? Does that mean I can now find things by just offsetting from that address, and does it mean that if I fwrite this whole block I'll essentially be fwriting the whole game?" "4142": "You can specify which functions to optimize by enabling optimization on the command line and surrounding code you don't want optimized with #pragma optimize("", off) ..... #pragma optimize("", on)" "4191": "Do you ever find use size_t or do you just use u32, u64, etc?" "4220": "Do you keep track of struct padding when you add / remove fields, or is it something you don't think about too much, so order of fields doesn't matter much?" "4256": "Also, what's the point of the core number in the debug info? It seems the thread ID is the important part" "4314": "Look forward to tomorrow" "4355": "How will we avoid collecting or displaying stats on debug-rendering code?" "4373": "Are profilers as bad as debuggers?" "4378": "What do you think about checked exceptions?" "4409": "Thanks and a few words on preordering the source and using the GitHub repositories" --- name: "day182" title: "Fast Thread ID Retrieval" markers: "36": "Recap and plan for today" "172": "On the benefits of having a nice inline profiling system" "310": "The profiling system is only slow in the collation phase, and that is acceptable" "405": "Limitations of the current implementation of the profiling system:" "468": "1) It is possible for the profiler to read bogus data under extremely improbable conditions" "640": "2) The debug records are not stamped with core and thread indices" "660": "The core indices are not that important..." "699": "... thread indices, on the other hand, are crucial" "813": "Two options to disambiguate between threads:" "817": "1) Getting a thread index" "872": "2) Generating unique IDs with an atomic operation to pair our begin and end timed blocks" "936": "Can we find out the thread index with a simple function call?" "984": "How does GetCurrentThreadId work?" "1098": "It looks like GetCurrentThreadId only issues a couple of instructions to get the thread ID back" "1167": "Thread local storage" "1259": "Segmented addressing" "1427": "Is there some intrinsic that allows us to replicate GetCurrentThreadId's behavior?" "1605": "Yes, _readgsqword" "1660": "Replicating the behaviour of GetCurrentThreadId" "1668": "Debugger: Step in there after the jump" "1791": "Testing our version" "1843": "It works!" "1883": "Recording the thread ID inside RecordDebugEvent" "1940": "Abstracting GetThreadId on the platform layer" "2155": "Unifying the timer counters of platform and game layers" "2218": "Exposing the debug system to the platform layer" "2428": "How do we find the locations of the debug structures?" "2495": "We could store them on the platform layer side..." "2529": "...or we could leave the debug arrays on the DLL side and use DLL binding to patch their addresses" "2574": "DLL binding with _declspec(ddlimport)" "2666": "Consolidating the debug structs into a single struct (debug_table)" "2920": "Using the TRANSLATION_UNIT_INDEX preprocessor symbol instead of RecordArrayIndexConstant" "2951": "Accessing only the debug_table from inside the debug-related routines" "3465": "Moving the necessary intrinsics to the platform layer" "3526": "Testing. There's a bug" "3642": "Getting rid of GlobalDebugEventArray" "3670": "And... we're back!" "3710": "Q&A" "3758": "What do you think is an effective way to get better at assembly? Go over a book / tutorial? Read the code disassembly in VS? Mike Acton can look at a piece of code for a couple of seconds and estimate how many cycles it takes and what the assembly code for it is. I'd like to reach that level one day" "3897": "We're actually a pre-recorded laugh track" "3908": "How would you deal with switching between multiple APIs in a single application (like software / hardware renderer)? Would it be structured similar to the platform layer?" "4295": "Why don't compilers expose API that gives us information about our code (access to the AST, etc.)? Because when we write a top-down parser we're essentially writing something that the compiler already has" "4475": "Are you still using the software renderer or did you move over to DirectX or OpenGL?" "4480": "At what point does a person become a good programmer? When do you think you became a good programmer?" "4546": "How do you handle programmer burnout / depression? Those days when you're just not in the mood to do anything, not productive, you're demotivated, you can barely do any coding, you'd rather do 'anything' else other than what you should be doing" "4659": "Do you really prefer to save two unconditional jumps (so the CPU pipeline won't be flushed at any chance) instead of Compiler & Platform Independence (referring to the GetThreadId part)?" "4728": "Why are you making an engine instead of a game?" "4887": "Do you think implementing a regex matcher is worth it / useful for meta programming?" "4901": "You seem to be pretty unhappy with the quality of modern software. Do you think programmers were better in the past? Is the software you produce always flawless and bugless? Asking seriously, just trying to understand your point more clearly. Thanks" "5241": "Wrap it up" --- name: "day183" title: "Platform Layer Debug Events" markers: "8": "Recap and plan for today" "116": "Removing the obsolete debug_frame_end_info" "135": "In place of that, we could have an array of counters for the platform layer translation unit" "185": "But we can also write directly to the GlobalDebugTable" "314": "Introducing manual_timed_block to have more flexibility recording events" "508": "Implementing BEGIN_BLOCK and END_BLOCK" "542": "Naming blocks so that we can pair BEGIN_ and END_BLOCKs" "590": "We want to avoid creating scopes for the only purpose of timing what's inside" "613": "Let's write the usage code first" "810": "Naming also the END_BLOCKs" "903": "Implementing the named BEGIN_BLOCK" "1114": "Implementing the named END_BLOCK" "1187": "Renaming TIMED_BLOCK as TIMED_FUNCTION" "1257": "Making the code compile after all the changes to the debug system" "1378": "Reintroducing TIMED_BLOCK and consolidating it with TIMED_FUNCTION" "1560": "There's a compilation problem related to BEGIN_BLOCK" "1652": "Debugging the macro by commenting parts of it out" "1686": "The problem was one of conflicting names" "1736": "Grabbing the GlobalDebugTable at DLL-load time" "1813": "Changing the type of the global debug table to be a pointer" "1928": "Introducing a placeholder GlobalDebugTable in the platform layer" "1980": "The program crashes" "2095": "We did not initialize the counter inside the timed_block constructor" "2106": "Testing the last changes. The platform layer writes now to a separate debug memory" "2131": "Hooking up the debug table from the game code after loading the game DLL" "2215": "The debug array could also live in the platform layer side, but that option would have its own problems" "2337": "The sharing of the debug_table could be better" "2410": "The platform counters still don't show up in the visualization" "2459": "We were not printing the platform layer records yet!" "2504": "Adding the RecordCount per translation unit to the debug table" "2762": "Figuring out the platform layer record count" "2862": "Testing again" "2917": "The Win32Loop closes after DEBUGFrameEnd is invoked, so its value is incorrect" "3025": "We want to have a way of establishing frame boundaries" "3080": "Introducing FRAME_MARKER" "3133": "New debug_event_type: DebugEvent_FrameMarker" "3254": "Testing it" "3310": "(Blackboard) Structure and plans for the debug log. We want to keep a history longer than one frame" "3422": "We need to allocate more memory. Maybe it should come from the platform layer" "3490": "Is the amount of data we want to keep in the static section going to be a problem?" "3573": "Instead of two ping-pong arrays, we have now sixty-four" "3630": "Now we can look across frames and we don't need the snapshots anymore" "3680": "Not as good as a circular buffer but it will do" "3763": "Q&A" "3791": "Are you going to start the hardware renderer before starting on game logic? Or are you going to wait until software doesn't cut it? Or are you waiting for Vulkan?" "3849": "Do you just use the blue line selector and green cursor to make it easier to follow on stream, or is that how you normally like it? I feel like it would get fatiguing on the eyes" "3874": "When do you think it is a good idea to use somebody else's library / system instead of implementing our own? (e.g. Do you use anything from the C standard library?)" "4028": "Missed the first half of the stream, are you saving the past 60 frames into a buffer?" "4060": "If a miracle happens and C++ starts doing things right and addresses the issues in the implementations of most of their features, would you use their features like templates etc., or stick to metaprogramming etc.?" "4082": "In the debug display, are we going to see something like Brendan Gregg's flame graphs (where function call depth is represented on the Y axis)?" "4107": "I think a lot of people would like to see how to write a hardware renderer, myself included" "4233": "Getting good at writing game engines: make lots of them or work on a few larger ones and continue improving them?" "4327": "Close it down" --- name: "day184" title: "Collating Debug Events" markers: "19": ""We have all the code"" "25": "Recap and plan for today" "185": "(Blackboard) Problems related to performance counter visualization" "212": "There's one straightforward approach to performance counter visualization that we could implement..." "256": "...but it poses some problems" "311": "We could sidestep the issue by building two separate views: one hierarchical, the other one a ranking of routines sorted by total decreasing execution time" "520": "Implementing DEBUGOverlay by writing the usage code first" "555": "Thinking aloud about the task" "826": "(Blackboard) We'll support the display of multithreaded routines by segmenting the bar charts into lanes" "1425": "Figuring out the structures that will allow us to draw the charts" "1654": "Testing the new code" "1670": "Filling out the collation structures" "1719": "We'll use an arena to collate the debug events and records..." "1888": "...which means we'll be recollating all the data every frame" "2094": "Testing that we are still running. The memory we'll use for collation should be in place now" "2101": "Collating the debug information" "2393": "(Blackboard) Which event arrays are we going to process?" "2456": "“Sometimes programming just doesn't make sense.”" "2467": "Make CollateDebugRecords() loop over the debug event arrays from oldest to newest" "2631": "Processing the debug event arrays" "2685": "Multithreading and the possible lack of strict rdtsc serialization could interfere with the ordering of the events" "2716": "We'll draw a new set of bars after each frame marker" "2965": "We'll ignore all events preceding the first frame marker we encounter" "3020": "Figuring out the relative clock of events inside a frame" "3138": ""I liked how that completed to nothings"" "3356": "Q&A" "3417": "You could have made your loop this way: for(u32 EventArrayIndex = InvalidEventArrayIndex + 1; EventArrayIndex != InvalidEventArrayIndex; EventArrayIndex = (EventArrayIndex + 1) % MAX_DEBUG_FRAME_COUNT) { ... }; Or did you want to save the modulo?" "3519": "Might not have a ton of on-topic questions. Chat was a bit... distracted" "3525": "What would be the most important things you'd look at when hiring a programmer? What type of questions would you ask? Does he have to have, like, 20+ years of experience?" "3654": "Do you think you do not need to ever worry about modulus or divides anymore?" "3742": "Which Linux debugger is closest to not sucking and what is it missing?" "3774": "On a scale of 1 to Visual Studio, why is Emacs a 1 and when will you join the visual studio master race?" "3850": "Sorry if this has been asked before, but what keyboard are you using?" "3899": "How did you get into Game Development?" "3968": "My girlfriend wanted to let you know that she has the same water bottle as you!" "4043": "What decision process do you use to choose the color of sweater to wear on a particular day?" "4068": "Will you please sign the contract with twitch so we can get good Casey emotes in chat?" "4081": "Have you seen the Poker keyboard series? It's very interesting in that it has all the keys in the center of the keyboard, you never have to leave the center row" "4093": "We'll keep you updated!" "4096": "Still using the 3 bin system for clothes?" "4100": "Does it ever happen to you when you sleep on a problem and then when you wake up the solution would just click in your head?" "4237": "Does it have to be at night, or just when you're sleeping?" "4267": "What time do you usually go to sleep?" "4273": "Could you please expand on what you meant by "in the future there won't be dedicated hardware for graphics"? You mean it'll be more CPU cores and ray tracing instead?" "4354": "Would you think in the next 5-10 years they'll move us from 64-bit to 128 bit?" "4373": "Wind it on down" --- name: "day185" title: "Finishing Basic Debug Collation" markers: "8": "Recap and plan for today" "82": "We left the code in a non-working state" "157": "Review of code from the previous day" "210": "Pushing debug frames into the collation memory arena" "280": "By using MAX_DEBUG_FRAME_COUNT as the size of our event arrays, we assume that only one frame end event will be issued per frame. Let's get rid of that restriction" "353": "Allocating debug_frames" "390": "Allocating debug_frame_regions" "475": "Testing. We are running out of debugging memory" "540": "What is the cause of that error? Are we processing too many frames?" "595": "We were treating the whole event array as if it was populated with real events!" "621": "The game runs now" "644": "(Blackboard) Problems we will face while pairing begin and end events" "922": "We will identify the events with a combination of their thread and counter ids. We will pair them using a stack" "1078": "Forbidding overlapping begin/end paired blocks" "1200": "Allocating storage for the stack to pair the debug blocks" "1378": "Using debug_thread to segregate debug blocks according to the threads that originated them" "1653": "Processing DebugEvent_BeginBlocks" "1774": "Setting the values of debug_blocks" "1842": "In DebugEvent_EndBlock we'll find the matching block, if there is one, and pull it out" "2019": "Finding the frame index associated to the BeginBlock that matches our EndBlock" "2180": "Drawing a debug region once we find an EndBlock" "2261": "Yawn" "2268": "On the perils of overeating" "2283": "We will normalize the size of the bar charts with respect to the beginning and ending clock values of the frame" "2503": "We will only draw top-level blocks, for the moment" "2652": "Removing matching blocks from the stack" "2731": "Implementing GetDebugThread" "2835": "Implementing AddRegion" "2990": "Scaling the bars using the frame's clock range" "3030": "Testing. The game seems to loop forever and hang" "3073": "The bug was that we were not initializing the thread id" "3120": "Still not running correctly" "3215": "After increasing the amount of top-level regions per frame, the program works but runs really slowly and does not show the debug bars" "3243": "Stepping through the code" "3271": "Keeping the largest FrameBarScale to scale our debug bars" "3454": "The scale for drawing seems wrong" "3546": "Let's hardcode the FrameBarScale for the moment for debugging purposes" "3622": "The debug visualization is still not showing properly" "3812": "We were not multiplying the scaling factor by the chart height" "3874": "Q&A" "3938": "Is there still going to be a debug visualization of the asset memory chunks?" "3961": "Can you make a mini episode about project management, outsourcing, freelance hiring, etc.? Programming is great but making a game takes more. If not, can you point to good resources on the topic?" "3980": "Do you use the same memory model as in HMH when writing utilities or meta programs, or do you just malloc and it wouldn't matter because the thing runs once, does its thing and closes?" "4112": "What are the pros / cons of viewing debugging information real time vs logging them and viewing them after the fact?" "4341": "Off-topic. People want you to actually drink chocolate wine some time. Are you up for it?" "4369": "Are you going to IndieCade in Culver City? Would you recommend it?" "4383": "Thank you very much for mentioning cmirror. It addresses a lot of my issues directly and is much more human readable. What was the GetToken written for? For config files? Doesn't seem like for C code" "4424": "How will you debug the OpenGL / Direct3D stuff when you will ship?" "4573": "Did I misunderstand mollyrocket.com update, or should there be a comic there today having something to do with your project?" "4670": "Wrap up here" --- name: "day186" title: "Starting to Debug Event Recording" markers: "8": "Recap and plan for today" "79": "We'll be debugging our event record visualization" "145": "Quick review of the code relevant to the task" "209": "Are we building the debug frames properly?" "242": "Checking that the frame count is correct" "332": "There are too few regions inside a frame" "378": "Stepping through the code looking for the cause of that error" "855": "There seems to be a problem with the BEGIN_ and END_BLOCK pairing" "1015": "Stopping when we hit the END_BLOCK event of the GameUpdate counter" "1066": "Implementing StringsAreEqual" "1312": "The opening and closing GameUpdate events don't match at all" "1404": "The hierarchy of nested events seems too deep" "1533": "Is END_BLOCK_ not working properly?" "1628": "Examining DrawRectangle" "1787": "DrawRectangle is called from multiple threads" "1897": "Could the code that deals with multiple threads be wrong?" "1923": "Stepping through the code at DrawRectangle events" "2000": "Drawing rectangles inside the debug code could be the cause of the bug" "2105": "What does the global debug table look like when we're timing DrawRectangle?" "2445": "Some more stepping through the code" "2560": "Examining event writting inside TIMED_FUNCTION" "2598": "There are too many end blocks for the same ThreadId" "2640": "Is GetThreadId wrong?" "2729": "Testing GetThreadId at thread creation time. It checks out" "2977": "Substituting TIMED_FUNCTION with paired BEGIN_ and END_BLOCKs to avoid constructor/destructor pairs" "3186": "We're out of hypotheses. Let's freeze some threads to run them in order" "3375": "The problem seems to disappear when we run the threads in order. But why?" "3550": "Verifying that GetThreadId returns a u16" "3600": "Perplexing bug" "3690": "Checking that EventArrayIndex is aligned to 8-byte boundaries" "3975": "Outsourcing the problem to the stream" "4013": "We could debug the problem in isolation, on a simpler version of the code" "4057": "Q&A" "4084": "Try running without timing DrawRectangle" "4244": "The MSDN documentation for __readgsqword states "These intrinsics are only available in kernel mode, and the routines are only available as intrinsics". If this is the case, how were you able to use __readgsqword to read out the thread ID? (I'm not really sure what the difference between kernel mode and user mode is)" "4330": "You said that it seems to work normally for a little while, then stops working when it's under stress. Maybe let the threads run wild for a little while, then freeze them? Or is this not possible with the debugger?" "4568": "Is it possible that the ArrayIndex part somehow got swapped out during begin / end records?" "4584": "Did you create your colors to be easy on the eyes? If not, how did they come to be?" "4601": "Didn't you remove the EndBlock call?" "4803": "handmade_render_group.cpp: Make DoTiledRenderWork a TIMED_FUNCTION" "4870": "handmade_render_group.cpp: Make IGNORED_TIMED_FUNCTION by a TIMED_FUNCTION again" "4970": "If the debug code is slower than the actual runtime of the game, how can we rely on the debug systems to give us accurate timing of how long things are taking in the game since they naturally take more time in debug mode?" "5119": "handmade_debug.cpp: Render debug information for fewer frames" "5342": "If I remember correctly from the other day, you discard events if buffers are full. Are you sure all buffers are big enough?" "5390": "build.bat: Switch to -O2" "5469": "Could it be threads running across a frame boundary?" "5581": "Leave it in a state where it is broken" --- name: "day187" title: "Fixing an Event Recording Bug" markers: "8": "On the headwind of live streaming" "53": "It would seem that the viewers of Handmade Hero solved the bug from the last stream" "181": "Description of the effects of the bug" "270": "Even with lots experience, difficult bugs will still happen" "348": "This bug was not so complicated, but its source laid outside what we considered to be the set of probable causes" "487": "The bug is probably related to incorrect translation unit indices" "602": "RecordDebugEvent may generate an incorrect translation unit index if it's not inlined by the compiler" "722": "Checking that theory" "841": "Is one of the timing functions in handmade_optimized not working properly?" "870": "Disabling optimizations" "912": "The bug does not reproduce in debug mode" "956": "Stepping though the optimized code" "1080": "RecordDebugEvent is not inlined" "1135": "Yes. Wrong translation unit. The forum nailed it" "1171": "Making RecordDebugEvent a macro fixes the issue, but..." "1218": "Owl of Success Moment" "1264": "... we should get rid of the code related to translation unit indices anyways; it introduces too much complexity and opens the door to subtle bugs" "1362": "We won't remove the translation unit indexing yet" "1458": "Back to visualization. Let's avoid producing regions that would be invisible in our debug plots" "1574": "Introducing options to compile away the profiling code" "1765": "According to the debug display, we should be running at a higher framerate" "1892": "Validating rdtsc measurements against wall clock time" "2010": "Recording the wall clock during FRAME_MARKER invocations" "2419": "Our display does not agree with the framerate because we are not taking into consideration the time it takes to collate debug records" "2483": "Selectively setting SecondsElapsed instead of ThreadId and core index" "2841": "HAL: "I'm sorry, Dave, I can't... I can't save the file"" "2900": "Testing today's additions. It's odd that the time we spend inside FrameWait and FrameDisplay went up" "3000": "Adding DebugCollation counters" "3030": "DebugCollation takes a lot time" "3069": "Using the wall clock times to print the time it takes to draw a frame" "3240": "We're at 250 ms/frame" "3274": "Without drawing the debug rectangles, it goes down to 91 ms/frame" "3345": "Disabling debug event recording, we get back to our original performance" "3554": "Our collation of the debug records is very expensive" "3636": "Q&A" "3665": "What's your favourite bug of all time?" "3708": "Often when I'm debugging, I have to stop myself from changing stuff at random because of mental laziness, hoping for "an even number of sign errors". Do you ever have that urge? If so, has it diminished as you have become more experienced?" "3919": "Doesn't it go against your philosophy of "write the code as you need it" to make a debugger like this before the game needs much debugging?" "4041": "Is there any way to keep familiar with old code or is working with it frequently the only way?" "4249": "Mok actually found the bug and AndreasK actually figured why it is causing what was happening by looking at the assembly. The compiler decided to not inline the call in the constructor and inline it in the destructor so the start marker is wrong and the end marker is right" "4341": "It looked like that FRAME_MARKER was going past this TODO: "// TODO(casey): Move this to a global variable so that there can be timers below this one?"" "4394": "win32_handmade.cpp: Move that TODO down and check if GlobalDebugTable exists" "4447": "Do you really care about compilation units or just threads? Hash the thread IDs" "4486": "Do you write code for this project off stream, for fun or speed?" "4524": "If I don't have a credit card, is there another way to buy it?" "4569": "You brought up your devlog: do you think that writing a devlog is good for the writer, the readers, or both?" "4585": "It sounds like the debugger is not only a tool to find out what is going wrong, but to detect when things are going to go wrong. Is that a fair assumption? I never thought of a debugger as something that keeps me "situationally aware". That sounds like a great idea" "4666": "We have come to the end of the stream" --- name: "day188" title: "Adding Hover to the Debug Graphs" markers: "15": "Recap and plan for today" "82": "The game runs slow because every frame we're collating all events for the past 64 debug frames" "130": "Decreasing the amount of debug frames we process from 64 to 8" "241": "We want to extract more information from the debug display" "380": "We want the debug display to show us information associated to any bar when we hover over it" "405": "Passing the game input to the debug system so that it can access the mouse position" "467": "Checking if the mouse position falls inside any given rectangle" "605": "The information to display will come from a debug_record associated to the debug_frame_region" "705": "Adding a debug record and a cycle count to debug_frame_region" "803": "Building a rectangle to test if the mouse pointer falls inside" "990": "Implementing a version of PushRect that takes a rectangle as its argument" "1064": "Testing. It runs but hovering doesn't work yet" "1106": "The mouse position is relative to Window' coordinate space, not to our rendering space" "1235": "Transforming mouse coordinates to the game space" "1350": "Hover works now" "1380": "Changing the position of the debug text on the screen" "1501": "Our ms/frame display shows 0 ms because we're computing it using the information from an unclosed frame" "1627": "We don't want the game layer to depend on Windows' representation of mouse position. The platform layer should transform it into the game's coordinate system" "1710": "Transforming the mouse position inside win32_handmade.cpp" "1830": "(Blackboard) If we want the leftmost and rightmost columns of our backbuffer to have the same absolute X, the (0,0) coordinate will fall on a pixel boundary" "2321": "Pausing collation" "2433": "Defining enumerands for mouse buttons" "2586": "Implementing WasPressed using the recorded HalfTransitionCount" "2706": "Testing. It does not work" "2721": "Cry about it" "2818": "We're not clearing the mouse state!" "2925": "Clearing the half-transition count at the start of each frame" "3036": "See if we can write something that's not total garbage" "3137": "Testing. It works" "3187": "Q&A" "3211": "Put the Pig Hat on the Owl" "3225": "You had four Owl of Shame moments" "3236": "Mouse code bugged for over 150 days, bring on the Owl" "3269": "Will almond milk make me smarter?" "3283": "And on behalf of all the people here, we love you and you are awesome" "3326": "I'm new here. Why constrain yourself to 1-hour segments? Isn't ramp-up time every day hard?" "3389": "How would you go about optimizing the debug rendering? It looks as though there is a lot of unnecessary work with EntityBasis calculation, etc." "3462": "build.bat: -O2 some of that up" "3537": "You've trained everyone to listen for whether you pronounce the letter "t", or its allophone, the glottal stop, when you say the word "buttons"" "3563": "Shoot, wasn't paying attention and I used the mouse code in another program. What was broken about it?" "3582": "At some point, would it make sense to pause and re-display the frame that is currently moused-over?" "3628": "By the way, I'm from iraq, and it's 4am right now. Can you some time do early stream? I don't mind not sleeping until 4am, but in 2-3 weeks university starts and it would be awesome if you bring back early hours" "3659": "I think you only render "top level" debug timed functions etc. Are you planning on "drilling down?"" "3672": "What is the other long bar? Some kind of frame wait? Should it be that long?" "3682": "Are you an indie developer and / or is this your professional job? If not, what is your day job?" "3707": "I forget if the white line is 33ms or 16ms. Could you add a green line for 60Hz, orange for 30, and red for 10, or something?" "3729": "I noticed in task manager that all of my Steam games are 32-bit processes. Is there a really good reason to compile games in 32-bits rather than 64?" "3800": "The debug display is for processing time. Are you going to do any visuals for memory usage?" "3844": "Would you be willing to do a 1-2 hour prestream?" "3860": "Wind it down" --- name: "day189" title: "Incremental Debug Frame Processing" markers: "10": "Recap and plan for today" "113": "Current features of the debug display" "169": "We want to be able to expand the top-level debug bars" "197": "Should the debug bars be horizontal?" "244": "Turning the chart sideways" "552": "Fixing the height of the bars" "600": "The debug rectangles don't fit in the screen even running an optimized build" "661": "Reviewing FrameRateWait" "786": "Turning FrameRateWait off" "819": "DebugCollation is very expensive" "924": "Processing frames incrementally to reduce collation time" "1005": "We want to avoid restarting the collation on each new frame" "1092": "We will restart the collation when we run out of frame storage" "1110": "Implementing RestartCollation" "1165": "Testing. It works" "1178": "Collating events in sweeps" "1212": "Restarting at the last event array index we used" "1322": "Storing the collation array index inside debug_state" "1368": "Testing that the game still runs" "1380": "Restarting collation when we run out of frames" "1484": "Adding CollationFrame to the debug_state" "1538": "Testing. It still takes a lot of time to run the event collation. Where is it spent?" "1659": "Are we hitting the debug event limit and restarting every frame?" "1696": "Testing. Collation still takes a lot of time" "1758": "Optimization makes it tolerable" "1800": "Why does right-clicking turn the debug display off?" "1906": "It happens both in optimized and non-optimized mode..." "1930": "Let's step through the code to debug this issue" "1997": "Why is DebugState not initialized?" "2055": "We never DebugState->initialized to true!" "2090": "And that solves the collation slowness problem" "2163": "Let's expand the timing bars" "2227": "Right now, we are throwing away all timing blocks under the top level" "2254": "Instead of showing the descendants of the top-level block, we will show the timing blocks whose source is a particular debug_record" "2445": "Implementing GetRecordFrom" "2487": "ScopeToRecord will allow us to move down the hierarchy of debug records" "2558": "When the left mouse button is pressed over a debug block, we'll set ScopeToRecord" "2600": "Testing it. It does nothing" "2680": "We need to recollate the events when we select a time block" "2780": "Implementing RefreshCollation" "2794": "Testing. It crashes" "2816": "Performing the collation refresh at the end of DEBUGOverlay" "2950": "Testing. It works now but sometimes we still hit the maximum limit of regions per frame" "3080": "Implementing TextOutAt, a DEBUGTextLine with explicit positioning" "3252": "Moving the time block debug information next to the mouse pointer" "3396": "Q&A" "3420": "Are the events keeping the same colors across frames? The long one looks like it keeps changing" "3452": "handmade_debug.cpp: Make the colors persist across frames" "3604": "handmade_debug.h: Add ColorIndex to debug_frame_region" "3708": "Does the 0.5 pixel error in yesterday's stream matter a lot? I mean, it seemed a pretty easy thing to overlook. Would it make some calculations erroneous?" "3761": "Why are there blank gaps on some of the bars? And why are the collated frames not flush with the other lines?" "3793": "Is there a reason why we have many different starting points for coordinate systems (center vs top-left vs top-right corners; windows vs Direct3D vs OpenGL)? Wouldn't our lives be easier if there was a standard for them?" "3849": "With handling sorting here, will we finally handle sorting of the other sprites in the game? Or will we just push that off further?" "3866": "Why do we have both bool32 and int32?" "3881": "Pretty cool! It does seem like a lot of calls take very different amounts of time even though they're probably not doing anything different. Is that due to other active processes? Is it usually worthwhile to try to get more consistent timings?" "3905": "How 'valuable' do you think C++ operator overloading actually is? I'm thinking of fully moving to just pure C. Do you think it would be inconvenient / a hassle to program without them? (Vector operations, etc.)" "3940": "Will you show us how to do hit detection for obscure shapes that may or may not exist in the debug UI?" "3967": "Have you seen the UE4 GDC Trailer and what are your opinions on it? I understand we are all indies, but just in general, from a player standpoint" "3994": "The longer bars (which I assumed was when the collation was happening) are farther left on the screen, than the shorter bars" "4030": "By obscure shapes, I mean a slice in a pie-chart" "4150": "Yes" "4264": "Yes the graphics. Check it out whenever" "4367": "[re functions taking different amounts of time] I mean, if we don't send any input and essentially the same image keeps getting rendered repeatedly, we still see a lot of fluctuation in the amount of time being consumed per frame. We have a lot of chop where I would have expected relatively calm waters (unless we're losing time to other processes on the machine)" "4512": "Curious what point represents the amount of time it takes the operating system to set up the parallelism, if parallelism is the right word" "4586": "Do you know why one of the worker threads started after the others?" "4636": "Every once in a while it seems like a frame gets missed; I've noticed that happens in things I do as well. Is there a way to get around that reliably?" "4716": "What do you think of the theory that says we already know everything, all the knowledge there is, but we just don't remember it? So when we study, etc. we start remembering things..." "4817": "Announce an announcement and sign off" --- name: "day190" title: "Cleaning Up Debug Globals" markers: "14": "The only reason we are writing a user interface is to support our debug system" "68": "Since we are the only users of the UI, we don't care if it's not intuitive, as long as it provides efficient interaction at a low implementation cost" "188": "Recap" "202": "Our approach to UI code" "285": "Initial plan for today: Turning off the profiling visualization" "429": "The debug UI can be a nice complement live code editing" "559": "Change of plans: We'll get rid of the global debug variables" "630": "Moving global variables inside the debug state" "650": "Making sure all routines have access to the debug state" "742": "It will be better to access the debug state through the DebugGlobalMemory. Implementing DEBUGGetState" "1035": "Testing. We got rid of those global variables" "1099": "The memory for the DEBUGRenderGroup comes from the transient arena. It should come from the debug arena" "1145": "Performing the DEBUGRenderGroup allocation inside DEBUGReset" "1206": "Access to the debug state should imply its initialization" "1340": "CollationArena will be a subarena of DebugArena" "1430": "Initializing the debug RenderGroup" "1472": "DEBUGReset will call BeginRender" "1542": "DEBUGOverlay will call EndRender" "1610": "The debug system shouldn't rely on the asset system; debug assets should be baked into the binary" "1965": "If we want the debug system to have access to the asset system, we need to make sure that the asset system is initialized first" "2038": "Implementing DEBUGStart and DEBUGEnd" "2349": "Testing. Live code editing and debug services work together now" "2410": "Resizing the profile view by changing its orthographic projection" "2683": "The mouse pointer position should also be transformed" "2727": "Controlling the placement of the profile rectangle" "2997": "Adjusting lane heights" "3217": "Displaying the profile rectangle so that we can debug the code that scales and positions it" "3401": "Fixing lane heights" "3660": "Q&A" "3700": "I appreciate that there are more robust ways of implementing such things, but would it be practical to use the debug data to drive some of the game's visual effects, e.g. fire or, more likely, some otherworldly magical entity or the display on an in-game computer? Maybe it could be a sort of Easter Egg for those of us who know how the game's made" "3765": "There are magenta spikes in the debug graph that happens so fast we don't have time to click on them. How do we plan to catch those? Having the ability to step-over frame-by-frame would be useful, methinks. Another idea is to have the debug text left off at the last rect position we hovered at" "3878": "Wrap it up" --- name: "day191" title: "Implementing a Radial Menu" markers: "7": "Recap and plan for today" "91": "Try something epically ridiculous" "182": "We want to be able to turn on and off parts of the debug interface" "270": "At the moment, the live looped code editing overrides our input, so it precludes interaction with the debug UI" "317": "Using the right mouse button as a "clutch"" "392": "Turning on and off the profiler" "463": "Start writing code at the place you know how to code" "589": "Drawing a radial menu" "648": "Let's pretend we have some menu items" "735": "Drawing the menu items" "820": "(Blackboard) Positioning text strings around a circle" "979": "Implementing Arm2" "1095": "Testing it. Looks OK, but are the labels centered?" "1110": "Marking the center of the circle" "1232": "Centering the text" "1320": "The code required to measure the dimension of labels has much in common with the code that draws them. Let's make sure the implementation of those operations does not fall out of sync" "1497": "Pulling the bitmap size computation out of PushBitmap to make it callable from other functions" "1729": "Defining debug_text_op" "1783": "PushBitmap will ignore non-loaded bitmaps" "1931": "Pre-pushing the debug font at DEBUGStart" "2100": "Fixing some compilation errors" "2170": "Computing the dimensions of a text string by computing the union of the rectangles of each of its glyphs" "2340": "Implementing the rectangle2 version of the inverted infinity rectangle" "2546": "Testing our new code. Implementing DEBUGGetTextSize" "2619": "Drawing the boundaries of the text labels to check their placement" "2730": "The placement of the labels is exact" "2740": "Some thoughts on the "operation" code transformation" "2821": "Centering the labels" "2897": "Finding out the menu index closest to the mouse pointer to change its color" "3194": "Activating menu items" "3217": "Do something like this" "3390": "Testing it" "3519": "Placing the radial menu relative to the mouse position at the time it was invoked" "3593": "Coming attractions" "3637": "Q&A" "3664": "I think you added v3.xy for v3-to-v2 conversion" "3706": "Even if the menus in the circle get cluttered, we could make it so that each button in the circle lead us to another circle / layer / subset of buttons" "3737": "Can you explain a bit more on that closure stuff and how to do it in C? I didn't quite understand it" "4077": "Why did you use radial menu over list or another format?" "4104": "It would be cool if the menu items are aligned with the circle borders, that way there's less chance of the text colliding" "4118": "You mentioned C doesn't officially support closures. Did you ever make an attempt to hack it, maybe via 'functors' or something like that?" "4140": "Have you ever considered a debug output for the stream where we can see your keystrokes?" "4163": "Anticipate mr4thdimention's editor 4coder" "4182": "Oftentimes when using somebody else's API / engine you end up having to 'fight' with it to have it do what you want from it. Do you think that is a sign that one should leave that API and try another / write his own instead of 'fighting' all the time?" "4518": "Are you ready for the world to end tomorrow as predicted by crazy Christians?" "4533": "Since draw rectangle quickly is in its own translation unit, are you going to write that code in straight ASM instead of C / intrinsics?" "4550": "Wait, isn't 4coder already better than Emacs?" "4570": "Can you go into detail on I/O Completion Ports since you brought them up?" "4585": "Wind it down" --- name: "day192" title: "Implementing Self-Recompilation" markers: "7": "Recap" "53": "Plan for today" "152": "Features and limitations of our current radial menu" "241": "We will build our UI around the debug features we already have" "350": "Let's find a way of turning debug features on and off easily from the debug interface" "391": "Quick review of the debug camera" "440": "There's a conflict between the reloading system and the debug event array collation" "513": "Maybe we should flush all events after a reload" "612": "Flushing the array event buffer" "735": "The DLL reloading already cleared that buffer. We only need to restart the collation process" "840": "Moving the ExecutableReloaded flag from the game input to the game memory" "899": "Testing it" "939": "The current way of switching between regular and debug cameras is inconvenient" "997": "We would prefer to automate the process of changing the code and recompiling it" "1082": "We will collect all switches inside the globally accessible handmade_config.h" "1203": "Be banana-cakes" "1221": "Assigning a type to config switches" "1256": "Rewriting the config file from inside the game code" "1321": "Implementing WriteHandmadeConfig" "1411": "We resort again to _snprintf_s to minimize the amount of CRT functions we will have to replace later" "1642": "Rewriting the config file after every debug UI action" "1697": "We want the game to recompile itself" "1715": "The platform layer will allow us to execute build.bat via DEBUGExecuteSystemCommand" "1945": "The OS function we are looking for is CreateProcess" "2310": "Testing it. It does not work" "2326": "CreateProcess returned false" "2369": "Using GetLastError to find out why" "2431": "Providing an explicit path to cmd.exe" "2492": "It works now" "2502": "Toggling the value of DEBUGUI_UseDebugCamera in the config file" "2559": "Introducing the Uber-Debug-UI!" "2588": "Getting rid of the compilation window pop-up" "2660": "Hiding the window using the wShowWindow flag inside the startup info parameter" "2800": "It works!" "2810": "Getting information about the state of the the compilation process" "3000": "We will use WaitForSingleObject to find that information" "3174": "Querying the platform layer about the state of the compilation process" "3348": ""We don't care big it is"" "3372": "Implementing DEBUGGetProcessState" "3511": "Using GetExitCodeProcess to confirm the completion of the compilation" "3725": "Signalling the ongoing recompilation graphically" "3801": "Find that platform_api doesn't have DEBUGGetProcessState" "3818": "Apologise for the slang" "3889": "Q&A" "3931": "Why be able to compile from the game if we can do it from the editor? Is it just to be cool?" "3990": "Compile in mr4th's editor and do all of the game development work from in-game?" "4011": "I like how it's "STARTUPINFO", but "PROCESS_INFORMATION". Inconsistency even in a single small part of the WinAPI... Do such things annoy you in a "professional" API?" "4053": "Why are we writing to a code file instead of just passing -D to the build line? Seems like it would be a little easier, although I have to admit you made that look pretty easy" "4104": "Why not use system() instead of CreateProcess()?" "4183": "Do you plan on reading the original config file and then rewrite with modified values?" "4192": "Why not just set a boolean variable instead of recompiling a #define?" "4238": "Will there be a dev console?" "4250": "Also, system() runs a program through CMD.EXE, which is yet another dependency" "4317": "The chat recommended CREATE_NO_WINDOW as a process creation flag. You could probably use that instead of the minimized window" "4358": "What is in the bat file that is run?" "4368": "Why does it zoom out?" "4382": "Are you using sublime?" "4387": "Can you add a radial menu for debug camera, instead of piggybacking off toggle graph? It's bugging me" "4399": "Shut down" --- name: "day193" title: "Run-time Setting of Compile-time Variables" markers: "8": "Recap" "41": "Plan for today" "103": "Review of last episode" "123": "We will be extending the debug system so that we can compile in and out debug features more easily" "201": "Optional compilation of ground chunk outlines" "287": "Optional compilation of the particle fountain" "307": "Why doesn't the particle system work?" "410": "The fountain depends on outdated font code" "420": "handmade.cpp: Go back to the head fountain" "452": "The game overwrote our changes to the handmade config file. Let's prevent that from happening again" "509": "Optional compilation of the particle grid" "528": "Optional compilation of room outlines" "568": "Fixing an outdated call to DrawRectangle" "748": "Optional compilation of ground chunk checkerboard patterns" "818": "Optional compilation of ground chunk reset on DLL reload" "940": "Optional compilation of weird renderer buffer sizes" "1094": "Finding out the correct findstr syntax to list all "#if 0" occurrences" "1240": "Optional compilation of the behavior that makes the familiar follow the hero" "1289": "Optional compilation of bilinear lighting sampling" "1329": "Optional compilation of the room-based camera movement" "1350": "The room-based camera is broken. Let's fix it" "1690": "It's working now" "1748": "We have enough items for the moment" "1795": "We want to know the values of our compilation switches to write them out to handmade_config.h" "1857": "The debug_variable struct will keep the names of the switches, their values and their types" "1911": "Defining them using the DEBUG_VARIABLE_LISTING macro" "2012": "Writing the variables to the config file" "2160": "What parameters does _snprintf_s require?" "2400": "Stepping though the code that builds the contents of the config file" "2445": "Writing the file worked" "2459": "Printing the variable list instead of the old menu items" "2512": "Toggling debug variables" "2588": "Testing. It works" "2622": "The run-time exclusion of pieces of debug code has some nice properties..." "2710": "...the only small catch is it still takes too many steps to add a new switch" "2774": "We would like the listing to upgrade itself automatically after a new variable is added, but parsing the code just for that may be going overboard" "2825": "Let's keep the variable listings in a separate file" "2911": "Our radial menu should allow us to _not_ select something once it's active" "3000": "Coloring menu items depending on their value" "3068": "Testing. The menu should not select an action when we remain at its center" "3126": "The compilation process is a bit slow, but we can skip the compilation of the asset builder" "3203": "Q&A" "3285": "I don't understand why a single if-statement would be expensive if we do it at runtime. Can you give an example?" "4074": "Why are we adding // b32 comment in the config file?" "4110": "Can you toggle the debug options while looping?" "4386": "You should add an optimization switch to the UI at some point" "4442": "Wouldn't -O2 optimize those dead branches out?" "4481": "Could you have an option to either recompile or simply toggle an "if"? It seems like most of the time you would use the regular "if" so the change is instantaneous, but in extreme cases you could easily just do the recompile option" "4585": "We are overtime" --- name: "day194" title: "Organizing Debug Variables into a Hierarchy" markers: "9": "Announcement: HandmadeCon 2015" "820": "Set the stage for the day" "924": "Recap where we left off" "1011": "Request some features" "1151": "Coin a phrase" "1277": "Take a look at the current debug code" "1517": "handmade_debug_variables.h: Introduce DEBUGCreateVariables" "1632": "handmade_debug_variables.h: Implement the ability to create groups of variables" "2073": "handmade_debug.h: Introduce debug_variable_group and debug_group" "2330": "handmade_debug_variables.h: Write DEBUGBeginVariableGroup and DEBUGAddVariable" "2736": "handmade_debug_variables.h: Write DEBUGEndVariableGroup" "2769": "handmade_debug_variables.h: Create debug_variable_definition_context" "2875": "handmade_debug.cpp: Call DEBUGCreateVariables" "3035": "handmade_debug.h: Add debug_variable *RootGroup to debug_state" "3103": "handmade_debug.cpp: Introduce WriteHandmadeConfig" "3465": "handmade_debug.cpp: Clean up compile errors" "3504": "handmade_debug.cpp: Call WriteHandmadeConfig" "3529": "Debugger: Step into WriteHandmadeConfig" "3619": "handmade_config.h: Look at the file we wrote out" "3651": "handmade_debug.cpp: Reinsert DEBUGUI_ at the front of the debug variables" "3681": "Debugger: Continue stepping through" "3702": "handmade_debug.cpp: Recap what we've done" "3777": "Q&A" "3813": "Can we make it an option to toggle between optimized and debug builds from the debug menu?" "3919": "Can you run the tool to see how many lines of code we have?" "3939": "Wouldn't it be prettier visually in our config files to be indented according to their group depth, that way we know which variables belong to which group? (i.e. variables in the root group don't have any indentation, group depth 1 will have a single level of indentation etc.)" "4180": "Linux / OS X Support [see Resources]" "4223": "Do you have any add-ons that you are using with emacs? Is it something like spacemacs?" "4235": "Off topic question: Are you using your razer on stream?" "4267": "Not running the game today?" "4276": "Was the intro talk about HandmadeCon included as part of the main hour of the stream?" "4284": "Switching between debug and optimized mode would not need a restart of the whole game?" "4312": "Can we sometimes see you play a game on twitch, like Jon does? Just a chill out stream. Would love to hear your opinion on many different games" "4340": "What about a Handmade Certification for games? A badge of honour, could be placed in a splash screen or in the credits. Products use certifications, e.g. Australian Made. Could be organised at the conference" "4412": "Thanks to you, I was able to implement dynamic code reloading for my project too! Saving me a ton of time" "4426": "Why Do I Have No Straem. I payed the micropayment" "4468": "handmade_platform.h: Implement the suggestions from the forums to enable SDL Handmade to run on Linux and OS X" "4883": "Does the idea for having your compile_switch / variable_switch speed cake involve compiling code out with "if(0)"?" "4905": "Why dont you use lua are you dumb" "4967": "How do you handle multithreading?" "4982": "Q: You inspired me to forget about my years of commercial experience writing RMGUIs and go and implement an IMGUI for my game engine. I love coding again!" "4996": "elxenoaizd: Someone asked a Q: about PushStruct on that day, so I'm guessing Casey MIGHT have introduced it then" "5003": "Q: Damn?" "5007": "How long have you been making games?" "5027": "Check unmatched parenthesis in #elif in ThreadID extraction" "5047": "What?" "5052": "Does streaming your development motivate you to do more / or more consistently?" "5076": "Did you use _snprintf or sprintf? The define is saying "change snprintf to _snprintf"" "5118": "Do you use any type of documentation or design for this project? What types of documents have you produced / planning to produce for this project?" "5162": "Wrap it up" --- name: "day195" title: "Implementing an Interactive Tree View" markers: "68": "Recap and set the stage for the day" "102": "handmade_debug.cpp: Consider cutting and pasting WriteHandmadeConfig" "208": "handmade_debug.cpp: Cut and paste it into DrawDebugMainMenu" "419": "handmade_debug.cpp: Initialise the menu" "542": "handmade_debug.cpp: Set the TextP and advance AtY" "650": "Run the game and see how it looks" "659": "handmade_debug.cpp: Indent the text based on the depth" "709": "Run the game and see our hierarchical printout" "725": "handmade_debug.cpp: Implement the ability to interact with the menu" "998": ""A Variable can be anything that it wants to be"" "1148": "Run the game and see our progress" "1161": ""That's a mistake"" "1174": "handmade_debug.cpp: Fix the test" "1241": "Run the game and demo a bug" "1274": "handmade.h: Introduce PushCopy" "1431": "handmade_debug_variables.h: Use PushCopy to copy Name to the stack" "1475": "handmade_platform.h: Move StringLength from win32_handmade.cpp" "1521": "Run the game and see that our strings do persist, but that we have a bug" "1614": ""There must be a bug"" "1628": "handmade_debug.cpp: Add an InvalidDefaultCase and clean up garbage in handmade_config.h" "1679": "handmade_debug_variables.h: Copy the null terminator onto the end of the Name string" "1753": "Run the game and find that everything's working nicely" "1774": "handmade_debug.cpp: Implement the ability to expand / collapse the tree" "1878": "Run the game and try out the newly compressed tree menu" "1900": "Consider adding more features" "1950": "handmade_debug.h: Add some more debug_variable_types" "2003": "handmade_debug.cpp: Use those variables in WriteHandmadeConfig" "2162": "handmade_debug_variables.h: Create some debug variables using those types" "2295": "Run the game and see our new debug_variable_type in action" "2321": "handmade_debug_variables.h: Consider implementing the ability to tweak values in the UI" "2390": "handmade_debug.cpp: Introduce DEBUGVariableToText to stick the prefix and suffix onto the variables" "2833": "handmade_debug.h: Introduce debug_variable_to_text_flag" "2864": "handmade_debug.cpp: Use DEBUGVariableToText" "3148": "Run the game and see that everything seems to be working, except for the handmade_config.h printout" "3179": "handmade_debug.cpp: Correct the carriage return and stop printing out groups in WriteHandmadeConfig" "3347": "handmade_debug.cpp: Introduce DEBUGVariableToText_PrettyBools" "3413": "Run the game and find that we're getting a little closer" "3445": "handmade_debug.cpp: Correct typos" "3531": "handmade_debug.cpp: Print out // before the groups" "3605": "Run the game and see that it all looks pretty good" "3646": "handmade_debug.cpp: Create a bunch more debug variable types" "3856": "Run the game, assess our progress and glimpse into the future" "3936": "Q&A" "3963": "That was pretty bools, man!" "3968": "Casey, we hear cutlery. Maybe skip Q&A and eat?" "3988": "Why aren't the + and - signs not shown for the group labels?" "4041": "Instead of manually typing values of power of 2 for our debug text enums can't we just use 1 << 1, 1 << 2, etc.?" "4059": "So is THIS what you meant by IMGUI?" "4087": "Colored text option for V4's representing colors?" "4095": "Will you be adding string type debug variables, maybe for things like save folder location, keybindings etc.?" "4115": "Why can't we use LLVM in windows? That way we use the same compiler for our major platforms" "4153": "printf comes from a library, we must implement string formatting so the stream isn't based on a lie" "4311": "If you had to implement an encryption system, would you use a library or write it from scratch yourself?" "4321": "(Off topic) How long after getting his / her number should you text / call them?" "4330": "Are you planning on doing user text input (i.e. spawn entity with x amount of health)?" "4335": "You missed my question twice in the prestream. Looks like it's not appearing. Is there a max question length that you filter out?" "4348": "You can debug LLVM things using the Visual Studio UI" "4365": "Would it be possible to compile all possible combinations of debug vars as separate binaries but then only use the one that matches the chosen debug vars, for faster switching? Is this a stupid question?" "4602": "What is the end goal for the Debug GUI? Like, at what point will we say this is done?" "4622": "In case the debug variables header is messed up, can we check easily if a debug variable is not defined and set some default value?" "4640": "How would you implement your own string without having them being null terminated? Bundle the char* with a count variable?" "4658": "Handmade Certification" "4773": "Wrap it up" --- name: "day196" title: "Introduction to UI Interactions" markers: "187": "Recap and set the stage for the day" "281": "Blackboard: UI Input Processing" "567": "handmade_debug.cpp: Explain how the code is structured for IMGUI" "755": "handmade_debug.h: Introduce *Hot, *InteractingWith and *NextHot debug_variables" "931": "handmade_debug.cpp: Introduce DEBUGInteract and build it up using those variables" "1324": "Run the game and see what happens" "1348": "handmade_debug.cpp: Determine whether the variable we're interacting with is Hot" "1466": "handmade_debug.cpp: Introduce DEBUGBeginInteract and DEBUGEndInteract" "1779": "handmade_debug.cpp: Implement the ability to modify the debug variables" "1960": "Run the game and see our current progress" "1974": "handmade_debug.cpp: Reimplement the ability to expand / collapse the tree menu" "2078": "Run the game and note an interesting situation regarding the interaction" "2180": "handmade_debug.h: Introduce debug_interaction" "2281": "handmade_debug.cpp: Test the interaction state in order to determine which type of interaction to perform" "2461": "Don't be premature" "2503": "handmade_debug.cpp: Perform different interactions depending on the DebugVariableType" "2720": "Run the game and check out our new ability" "2742": "handmade_debug.cpp: Check that we have a variable and rerun the game" "2773": "handmade_debug.h: Add NOP to debug_interaction" "2851": "Run the game and try out this new NOP interaction type" "2876": "handmade_debug.h: Introduce debug_variable_hierarchy" "3095": "handmade_debug.cpp: Setup the hierarchy" "3265": "Debugger: Step in to DEBUGDrawMainMenu to find where everybody went" "3333": "handmade_debug.cpp: Flip the order of the values passed to DebugState->Hierarchy.UIP" "3352": "Run the game and find that it's all working" "3391": "Q&A" "3426": "Once you finish making the game, you you do a live playthrough?" "3537": "We're getting close to 200 episodes; how long do you think until you start on the game proper?" "3758": "Does this mean a proper RNG is around the corner?" "3897": "Did you already cover the Minkowski difference on stream?" "3966": "Could you explain the difference between how IMGUI is often implemented, and how you think it should work again? It went a bit fast for me" "4073": "Would you ever consider doing a 24-hour stream that was create X app or game from start to finish in one stream?" "4150": "Close" --- name: "day197" title: "Integrating Multiple Debug Views" markers: "9": "No plan for today. We will pull together the debug UI code but we still don't know how" "105": "Current state of the debug UI" "141": "We want to bring the debug system to closure, to modify it so that it's convenient to use in the future" "204": ""Oh games, they're so wacky and weird"" "209": "We will try to unify the debug UI and the profile view" "240": "We could integrate the profile display as an element of the debug variable hierarchy" "281": "Introducing a new debug_variable_type enumerand for the profile system" "322": "Reviewing the structure of the profile display code to think on how to integrate it" "472": "Rethinking the profile enumerands" "543": "Adding the profile display to the hierarchy by making the debug_variable_definition_context explicit" "756": "We won't be turning these new variables into text" "801": "Filtering out profile counter variables so that they're not written to the handmade config header file" "874": "We need to generalize the rendering of UI elements to take into account the profile display" "1030": "Inserting the profile display into the hierarchy" "1066": "Defining the bounds of the profile display" "1199": "Drawing the profile display into those bounds" "1366": ""Meh nnn hh meh"" "1452": "AtY will now denote the upper-left corner of an element, not the baseline of the text" "1564": "Debugging the placement of the UI items" "2075": "Their positioning is still a bit faulty" "2095": "Collapsing the profile view" "2174": "Finishing the text positioning" "2242": "The text strings line up properly now" "2314": "Including a second profile display to list show counters by function" "2384": "We want to be able to resize the profile views" "2545": "We'll introduce a small handle so that the user can resize them" "2735": "There are several ways to treat the resize handler. We will let the caller suggest the interaction that should be performed" "2968": "If the click happens inside the resize rectangle, we set the HotInteraction to resize the profile view" "3105": "Highlighting the resize control when hovered upon" "3165": "Interacting with the resize control" "3240": "Debugging the new code" "3361": "It's working!" "3384": "Normally we would set the size of the display by measuring the distance from the point where the down-click happened to the current position, but this is internal debug code" "3473": "Introducing a root group" "3525": "Q&A" "3559": "Do you think this way of structuring UI code could be used to build a full application, or is it just useful for debug UIs? What extra things do you think you'd need to add to make it useful for a full app UI?" "3730": "Were you nervous the first time you streamed Handmade Hero?" "3838": "What do you think about GCC and its dbg?" "3891": "Did you ever get your IRC fixed to show names again?" "3907": "Have you considered working at Valve? What is your opinion of them and their structure?" "4085": "What will the game look like in 25 episodes?" "4194": "Will you be using profiling tools (like gperf) to find hot spots in the code, or rely on your own debug system only?" "4331": "Have you met Michael Abrash or Carmack in person?" "4418": "Are you going to see The Martian?" "4451": "You talked about projects you'd like to program. We are seeing a bunch of space games now after being without decent ones for a while. Are you interested in space games at all?" "4577": "Kerbal Space Program?" "4609": "When is the next Casey drink+game night?" "4646": "Star Citizen is crashing and burning" "4776": "How did you end up working on The Witness, and what is it like to get jobs as a 'freelancer'?" "4830": "If Star Citizen _does_ end up delivering, do you think it has the potential to change the current publisher AAA model or do you think it will be a one-shot regardless of its success?" "4902": "Start to wind it down" "5002": "Wait, is there a limit?" "5087": "Finish winding it down" --- name: "day198" title: "Run-time Editing of Debug Hierarchies" markers: "138": "Recap and set the stage for the day" "271": "handmade_debug.h: Introduce debug_variable_reference" "484": "handmade_debug_variables.h: Introduce DEBUGAddUnreferencedVariable" "583": "handmade_debug.h: Add debug_variable *Var to debug_variable_reference" "591": "handmade_debug_variables.h: Introduce DEBUGAddVariableReference" "735": "handmade_debug_variables.h: Clean up compile errors" "851": "handmade_debug.cpp: Propagate Ref out" "976": "Compile and see that it still works" "995": "handmade_debug_variables.h: Try adding a UseDebugCamRef into two different groups" "1086": "Run the game and see UseDebugCam in two groups" "1131": "handmade_debug.cpp: Implement the ability to have more than one debug_variable_hierarchy" "1466": "handmade_debug.cpp: Introduce AddHierarchy" "1652": "handmade_debug.cpp: Write the Hierarchy doubly-linked list" "1782": "Debugger: Step in to AddHierarchy" "1875": "handmade_debug.cpp: Call AddHierarchy in the correct place" "1947": "Run the game and find things in better shape" "1978": "handmade_debug.cpp: Implement the ability to tear items off the menu" "2339": "handmade_debug.cpp: Implement DebugInteraction_TearValue" "2474": "handmade_debug.variables.h: Introduce DEBUGAddRootGroup" "2708": "handmade_debug.cpp: Call DEBUGAddRootGroup" "2832": "handmade_debug_variables.h: Make DEBUGAddVariableReference take debug_variable *Group" "3011": "handmade_debug.cpp: Call DEBUGAddVariableReference" "3064": "handmade_debug_variables.h: Make DEBUGAddRootGroup add a debug_variable_reference" "3120": "handmade_debug_variables.h: Introduce a new DEBUGAddRootGroup and rename the original to DEBUGAddRootGroupInternal" "3287": "Run the game and test out our new tearing ability" "3345": "handmade_debug.cpp and handmade_debug.h: Introduce DebugInteraction_MoveHierarchy" "3445": "handmade_debug.cpp: Draw a MoveBox for each Hierarchy" "3521": "handmade_debug.cpp: Implement the ability to move that Hierarchy" "3571": "handmade_debug.h: Add debug_hierarchy *NextHotHierarchy to debug_state" "3734": "Debugger: Step in to DraggingHierarchy" "3778": "handmade_debug.cpp: Clear NextHotHierarchy" "3794": "handmade_debug.cpp: Introduce DEBUGTextLine to display when we are interacting" "3862": "handmade_debug.cpp: Make the check be on HotInteraction" "3925": "Run the game and try that again" "3955": "handmade_debug.cpp: Move Assert(Var)" "3982": "Run the game and check out our tearing and moving abilities" "4020": "Q&A" "4067": "No questions" "4084": "You mentioned that encapsulation is good but not in the OOP way. Could you elaborate then in which way you mean?" "4149": "Are the menu items spaced evenly vertically? Looks a bit odd to me" "4165": "handmade_debug.cpp: Use LineAdvance to space the lines" "4609": "Why is there so much lag / latency when dragging the hierarchies around? Or is that just Twitch streaming artifacts?" "4688": "Are the different tear-offs intended to have identical hierarchies or is the intention that you drill down into different things without all the tear-offs being affected?" "4752": "I noticed you use the internal keyword. I haven't seen it before. What is its purpose?" "4763": "I apologize since I came in late, but out of curiosity, what was the tolerance (in pixels) you used for dragging out a subsection?" "4778": "You mentioned that for linked lists at work you use metaprogramming. What did you mean?" "4791": "I missed 90% of the stream, so I missed a ton. I just want to ask what are some tips for people who want to get into designing games? Dos and Don'ts and simple things that are worthwhile" "4802": "Does anyone know if there is plans in the future to add other platform support to this project?" "4823": "Have you ever written anything for the PS1? (I think Jeff mentioned he used to do some stuff in a J&C episode?)" "4827": "Have you ever played any of the Space Quest games? The music for the video on the Handmade Hero site reminds me of it a lot" "4847": "Do you plan doing something with the character spacing in the text renderer?" "4862": "Is 'sentinel' a design pattern that will help with making the torn instances of the UI independent, or is that terminology that you've gained in years of tool development? Now that I understand what you meant by 'tearing' the interface, it seems really useful for isolating instances of hierarchies" "4891": "Not a huge deal, but the labels no longer show if clicking them will expand or minimize them. Also at a glance it is not clear what is a category and what is a var" "4908": "Which game console had the worst SDK?" "4936": "Wrap it up" --- name: "day199" title: "Reusing Debug Interactions" markers: "109": "Recap and find that we must have broken something" "161": "Debugger: Step through DEBUGInteract" "246": "handmade_debug.cpp: Identify the problem and set DebugState->InteractingWith in a different place" "344": "Run the game and find that we're fine" "382": "handmade_debug.h: Introduce a new debug_interaction and rename the old one to debug_interaction_type" "505": "handmade_debug.h: Simplify debug_state" "572": "handmade_debug.cpp: Make DEBUGDrawMainMenu work with this new structure" "736": "handmade_debug.cpp: Introduce InteractionsAreEqual" "793": "handmade_debug.cpp: Continue working on DEBUGDrawMainMenu" "894": "handmade_debug.cpp: Introduce InteractionIsHot" "935": "handmade_debug.cpp: Continue cleaning up DEBUGDrawMainMenu" "1053": "handmade_debug.cpp: Make DEBUGBeginInteract work with the new structure" "1275": "handmade_debug.cpp: Make DEBUGEndInteract work with the new structure" "1392": "handmade_debug.cpp: Make DEBUGInteract work with the new structure" "1535": "handmade_debug.cpp: Make DEBUGEnd work with the new structure" "1549": "Run the game and hit an assertion" "1576": "handmade_debug.cpp: Set these variables in DEBUGBeginInteract" "1724": "Run the game and find that things are better" "1763": "handmade_debug.h Add v2 *P to debug_interaction" "1796": "handmade_debug.cpp: Use that *P in DebugInteraction_Resize and DebugInteraction_Move" "1862": "handmade_debug.h: Add DebugInteraction_Resize and DebugInteraction_Move to debug_interaction_type" "1878": "handmade_debug.cpp: Continue adding that P" "1942": "Run the game and try interacting with the menu" "1982": "handmade_debug.cpp: Give DebugInteraction_TearValue an interaction" "2047": "Run the game and test this generic moving" "2085": "handmade_debug.h: Extend this notion of generic movement to another debug_variable_type" "2131": "handmade_debug.h: Introduce debug_bitmap_display" "2188": "handmade_debug.cpp: Implement DebugVariableType_BitmapDisplay" "2380": "handmade_debug_variables.h: Introduce a DEBUGAddVariable for bitmap_id" "2662": "Run the game and hit the InvalidDefaultCase" "2708": "Add DebugVariableType_BitmapDisplay to DEBUGShouldBeWritten" "2729": "Run the game and try out the resize interaction" "2755": "Consider how best to resize bitmaps directly without using the alignment offset" "2895": "handmade_render_group.cpp: Implement the ability to turn the alignment off" "3057": "Run the game and find it's correctly resizing" "3081": "handmade_debug.cpp: Draw the Bounds of the guy" "3113": "Run the game and consider the aspect ratio" "3183": "handmade_debug.cpp: Implement the same resizing for the bitmap as for the font" "3353": "Run the game and find that the resizing works much better" "3544": "Q&A" "3657": "Maybe I'm misunderstanding, but is it desired behavior for the "tear" feature to tear all groups below it even if they are on the same level in the hierarchy? I would think you would only want to tear the current group and subgroups, not other groups on the same level. For example, you wouldn't want the "profile" group to get torn when you tear the "particles" group" "3736": "If I bought a ticket for the Con that I can't use, can I donate it to someone?" "3754": "Can the new bitmap display be torn off as well?" "3782": "handmade_debug.cpp: Allow the bitmap to have an ItemInteraction" "3939": "Is it worth doing so much UI work if the game will not feature much UI?" "4032": "Can you add variables to change the match vectors?" "4114": "Will there be a menu system like pressing start in Zelda to change items? Nothing fancy, but just something to get us started on how to do it" "4196": "Assume that we have Q:'d out" --- name: "day200" title: "Debug Element Layout" markers: "110": "Recap and set the stage for the day" "317": "handmade.debug.cpp: Look at how we're currently drawing things" "437": "handmade_debug.cpp: Introduce layout struct to contain local variables" "602": "handmade_debug.cpp: Introduce Advance" "921": "Run the game and find that it's the same as it was" "930": "handmade_debug.cpp: Introduce PlaceRectangle" "1121": "Run the game and find that it just works" "1131": "handmade_debug.cpp: Use PlaceRectangle to compute the layout of elements for us" "1223": "Run the game and show the elements using the same layout routine" "1250": "handmade_debug.cpp: Consider the difficulty of pulling out the SizeP computation" "1445": "handmade_debug.cpp: Simplify and loft out computations from DEBUGDrawMainMenu" "2030": "handmade_debug.cpp: Introduce BeginElementRectangle, MakeElementSizable, DefaultInteraction and EndElement" "3243": "Run the game and spot a mistake" "3260": "handmade_debug.cpp: Only push the rects if the Element has a Size and stop making Text elements Sizeable" "3305": "handmade_debug.cpp: Add the DefaultInteraction" "3363": "Run the game and see that everything seems to be working pretty well" "3465": "Q&A" "3630": "Why don't you connect to chat with your desktop?" "3767": "Set the stage for the evening and wind it down" --- name: "day201" title: "Isolating the Debug Code" markers: "107": "Recap and hit a first-chance exception" "158": "Investigate this exception" "362": "win32_handmade.cpp: Move DebugCollation above FramerateWait and pass NewInput and &Buffer to DEBUGFrameEnd" "450": "handmade.cpp: Remove DEBUGStart and DEBUGEnd" "474": "handmade_debug.cpp: Call DEBUGStart and DEBUGEnd in DEBUGGameFrameEnd" "666": "handmade.cpp: Introduce DEBUGGetGameAssets to enable the debug system to get the TranState->Assets out" "757": "handmade_platform.h: Give DEBUG_GAME_FRAME_END the same call structure as GAME_UPDATE_AND_RENDER" "803": "handmade_debug.cpp: Create a DrawBuffer for the debug system" "900": "Debugger: Step into DEBUGGetState" "932": "handmade_debug.cpp: Paste DEBUGGetState into DEBUGGameFrameEnd" "1010": "Run the game and find that we're in better shape" "1111": "handmade.debug.h: Consider getting rid of this header file entirely" "1192": "handmade.cpp: Add conditional on HANDMADE_INTERNAL to enable us to toggle the debug system" "1272": "build.bat: Turn off HANDMADE_INTERNAL" "1287": "handmade_platform.h and win32_handmade.cpp: Add conditionals on HANDMADE_INTERNAL" "1367": "handmade_platform: Remove HANDMADE_PROFILE in favour of HANDMADE_INTERNAL" "1505": "Run the game successfully" "1517": "build.bat: Toggle HANDMADE_INTERNAL and still run successfully" "1606": "Think about how to proceed" "1740": "handmade_debug.h: Move the contents of debug_variable_group into debug_variable_reference" "1852": "handmade_debug.h: Consider splitting the variables up" "1983": "handmade_debug.h: Rename debug_variable_ structs to debug_tree and debug_tree_entry" "2033": "handmade_debug.h: Introduce debug_tree_entry_group" "2081": "handmade_debug.h: Rewrite debug_tree" "2204": "handmade_debug.h: Introduce debug_tree_entry_window" "2278": "handmade_debug.h: Introduce debug_tree_entry_type" "2325": "Recap these changes" "2392": "handmade_debug.h and handmade_debug_variables.h: Clean up the compile errors" "2511": "Consider using a caching-centric system" "2681": "handmade_debug.h and handmade_debug_variables.h: Start to implement a caching-centric system" "3857": "Pause this temporarily and turn off HANDMADE_INTERNAL" "3897": "Q&A" "3925": "Now that the amount of debug code is getting larger, will you create a debug debug system to debug the debug code?" "3964": "Is this the link you were looking for earlier for MartinCohen?" "4027": "What do you think about the use of pre-fetch cache instructions? Are they a viable option for general purpose programming to get maximum performance?" "4108": "After the two year period, will we be able to mod the game?" "4117": "Does the architecture of your target system have a big effect on how you design your debug system?" "4191": "Would be it an idea to pass build.bat a parameter which you would use to switch optimisation on and off on the different build units? Like IF %1 == opt, do this, otherwise do that" "4229": "What do you think about "No Man's Sky"? I can't even think about how it works now. Will I get some idea after learning from you?" "4288": "I mean, after you release the source code. Will we be able to create our own bosses, worlds, etc.?" "4308": "Will you be returning to game specific coding soon?" "4421": "Could something like a Raspberry Pi or other ARM desktop PC run Handmade Hero well enough, and is that the kind of system where you would want to do the debugging on a separate machine?" "4487": "I meant for usage inside the game, so you could switch optimisation on and off from the debug menu" "4526": "Do you think it would be totz baller to make a GUI visual language for game scripting like what Unreal has?" "4574": "Blackboard: Visual Scripting" "4715": "Couldn't you collate just the last frame every frame instead of doing all of them in chunks?" "4822": "Close this down" --- name: "day202" title: "Multiply Appearing Debug Values" markers: "28": "Debugger: Enabling "Go To Definition / Declaration" feature" "190": "Internet: Building Browse Information Files: Overview" "240": "build.bat: Add -FR flag" "438": "Debugger: Show a dummy win32 project with this browse info enabled" "475": "build.bat: Remove -FR flag and delete the *.bsc and *.sbr files" "493": "Recap our current status" "539": ""Patience is a virtue"" "732": "Set the stage for the day" "835": "handmade_debug.h: Introduce debug_variable_link" "910": "handmade_debug_variables.h: Introduce DEBUGAddVariableToGroup" "1038": "handmade.h: #define DLIST_INSERT" "1120": "handmade_debug_variables.h and handmade_debug.cpp: Use this DLIST_INSERT macro" "1199": "handmade_debug_variables.h: Continue cleaning up" "1257": "handmade.h: #define DLIST_INIT" "1325": "handmade_debug.h: Consider whether we want to store parent pointers for variables" "1405": "handmade_debug_variables.h: Introduce debug_variable_group_builder to enable DEBUGEndVariableGroup to pass the parent VarGroup back" "1507": "handmade_debug_variables.h: Add a GroupDepth and *GroupStack array to debug_variable_definition_context to show another way to solve this problem" "1753": "handmade_debug.cpp: Initialise that GroupStack in debug_variable_definition_context" "1867": "handmade_debug_variables.h: Continue on cleaning up compile errors" "1985": "Blackboard: Traversing trees using pointers and then stacks" "2288": "handmade_debug.cpp: Add *Stack to WriteHandmadeConfig " "2511": "Blackboard: The natural order of the stack" "2740": "handmade_debug.cpp: Introduce debug_variable_iterator to augment the stack" "3159": "handmade_debug.cpp: Continue cleaning up compile errors" "3255": "handmade_debug.cpp: Unwind the stack iteration loop" "3385": "handmade_debug.cpp: Use our stack implementation in DEBUGDrawMainMenu" "3445": "handmade_debug.cpp: Continue cleaning up compile errors" "3646": "handmade_debug.cpp: Introduce a dummy GetDebugViewFor" "3678": "Correctly spell "variable"" "3687": "handmade_debug.cpp: Finish cleaning up compile errors" "3829": ""That's the end of that"" "3891": "Q&A" "3919": "Does it work?" "4052": "Earlier in the stream you said that you once spent 10 weeks on a problem. What was that problem?" "4143": "Have you considered using intrusive linked lists like those in the Linux kernel that use offsetof()" "4203": "How portable will the game engine be? Could it be used to make other games?" "4242": "Curve Solver?" "4265": "Will we ever see the memory chunk debug visualization?" "4352": "What flavour of Linux on your laptop today, and what will it be on Monday" "4382": "By the way, I think the Linux kernel implementation can have something in multiple lists at once" "4404": "Blackboard: Linked lists" "4475": "Can you give me a quick rundown again of how you're substituting the stack for instances of the debug view?" "4501": "So what do you use as a "formatting language" usually?" "4555": "Is this how you do UI in your other programs?" "4604": "Call it done" --- name: "day203" title: "Debug UI State Caching" markers: "59": "Recap our current situation" "139": "Blackboard: Breadth-first vs depth-first tree traversal" "526": "Debugger: Step into DEBUGDrawMainMenu and hunt for the hierarchy" "805": "handmade_debug_variables.h: Make DEBUGAddVariable call the correct Context" "818": "handmade_config.h: Manually rewrite the config" "882": "Debugger: Step through and hit a first-chance exception" "920": "Debugger: Inspect the DebugState->RootGroup" "993": "handmade_debug_variables.h: Set Link->Var in DEBUGAddVariableToGroup" "1009": "Run the game and find it's looking a little bit better" "1039": "handmade_config.h: Ensure that the write-out worked correctly" "1063": "handmade_debug.cpp: Test for View->Collapsible.ExpandedAlways to be true" "1157": "Run the game and find that everything is collapsed" "1177": "handmade_debug.h and handmade_debug.cpp: Add debug_view Dummy to debug_state and make GetDebugViewFor return it" "1210": "Run the game and see the debug menu expand briefly" "1228": "handmade_debug.cpp: Finish implementing GetDebugViewFor" "1469": "Run the game and see that it's almost working fine" "1485": "handmade_debug.h: Consider storing the debug_view in debug_variable_link" "1615": "handmade_debug.h: Introduce debug_id" "1671": "handmade_debug.cpp: Pass ViewID to GetDebugViewFor" "1701": "handmade_debug.cpp: Introduce DebugIDFromLink" "1755": "handmade_debug.h: Add debug_id ID and debug_variable *Var to debug_interaction" "1812": "handmade_debug.cpp: Revert the code in DEBUGEndInteract and DEBUGInteract" "1867": "handmade_debug.cpp: Introduce VarLinkInteraction in order to compress these routines" "2028": "handmade_debug.h: Add debug_view *ViewHash to debug_state" "2140": "handmade_debug.cpp: Implement a hash function in GetDebugViewFor" "2433": "handmade_debug.cpp: Introduce DebugIDsAreEqual" "2485": "Run the game and see that our stuff works, except for indentation" "2549": "handmade_debug.cpp: Set the Layout.Depth in order to fix the indentation" "2628": "Run the game and see that the indentation is working pretty well" "2682": "handmade_debug_variables.h: Investigate why the Real32 isn't working correctly" "2768": "handmade_config.h: Try manually adding .0f to DebugCameraDistance" "2795": "Run the game and find that DebugCameraDistance is working" "2827": "handmade_debug.cpp: Reimplement tear-offs" "3027": "handmade_debug_variables.h: Introduce DEBUGAddVariableToDefaultGroup" "3090": "Run the game and find that the tear-off behaves as it did before" "3138": "handmade_debug.cpp: Grab the correct group in DEBUGDrawMainMenu" "3218": "Run the game and tear off specific values" "3258": "handmade_debug.h: Make DebugIDFromLink and VarLinkInteraction take the Tree" "3335": "Run the game and see that the state is isolated" "3398": "Recap today's work" "3470": "Q&A" "3494": "Pure design question. In GetDebugViewFor() your method is named such that it's a query but it appears to be a command in some cases (in that it changes the state of the system). I've heard that you typically want to avoid this. Do you agree? Is there a reason you did this?" "3593": "Do you think learning all the algorithms and data structures is a must, or is it OK to learn them when the need for one of them rises? Or is it one of those things that you have to learn beforehand in order to know if you need them or not?" "3721": "4bugger... No libraries. You need a new game maker?" "3736": "Q: Binary search tree is a subset of BTree, I think" "3787": "About your memory allocation (way back when): Shouldn't the amount of memory you allocate depend on the size of the world chosen by the user? As it is, it is fixed at compile time (if I understand correctly)" "3929": "I would like to be a tools programmer / game tech writer like you, but I'm still learning things so I'm not fully qualified to work as one. I'm thinking of working in a simple game company where the qualifications aren't so hardcore (maybe they use Unity or whatever), and at the same time do my private low-level self-learning. Good idea? Yes / No" "4115": "What are your plans for streaming once you complete this game?" "4126": "You've discussed using Blender. Are you a 3D modeller of some sort? More specifically, what operations do you do with that software package?" "4209": "I'd like to see a Blender pre-stream demo" "4230": "Would you consider doing a short off-hours stream to show people how you do things (like metaprogramming) that you won't get to touch on in Handmade Hero?" "4268": "Hey, love catching the stream when I can. What language do you recommend as a beginner programmer looking to get into game development?" "4491": "Stream is over" --- name: "day204" title: "Unprojecting the Mouse Cursor" markers: "8": "Announcement: Miblo's Patreon" "184": "Recap and set the stage for the day" "256": "Run the game and see where we're at" "341": "Consider moving away from explicitly constructing the debug hierarchy" "531": "On writing the usage code and then unifying the systems" "614": "handmade_sim_region.cpp: Look at how the entities are currently handled" "669": "Implement the ability to click on an entity in order to inspect it" "791": "Run the game and illustrate what we'd like to do" "948": "handmade.cpp: Introduce DEBUGUI_DrawEntityOutlines" "1085": "Run the game and see the new outlines" "1114": "handmade_render_group.cpp: Make PushRectOutline additionally take a Thickness" "1146": "Run the game and see the thinner magenta outlines" "1199": "Consider the problem of the perspective transform" "1309": "handmade_render_group.cpp: Look at Unproject" "1399": "Blackboard: Why we need the distance from the camera" "1526": "Blackboard: Conceptualising this entity picking" "1628": "handmade.cpp: Unproject the MouseP" "1766": "handmade.cpp: Test the LocalMouseP against the 2D entity Volume->Dim" "1965": "handmade.cpp: Do a PushRect of the mouse's location" "2020": "handmade.cpp: Do an Orthographic call to draw the MouseP" "2187": "handmade_render_group.cpp: Add OffsetP and Scale to Orthographic" "2256": "Run the game and see the mouse" "2292": "Debugger: Step into GameUpdateAndRender and inspect the MouseP" "2349": "handmade.cpp: Try and draw the LocalMouseP" "2437": "Run the game and don't see the LocalMouseP" "2462": "handmade.render_group.cpp: Investigate why we're not seeing the LocalMouseP" "2624": "handmade.cpp: Multiply the mouse's Transform by PixelsToMeters" "2742": "Run the game and see that the rects aren't correctly positioned [tl;dw: see 1:39:32]" "2779": "handmade.cpp: Investigate why rects aren't correctly positioned" "2897": "handmade.cpp: Pass the entity's Transform to the Unproject call" "2947": "Run the game and see that we're getting a little closer" "3067": "handmade.cpp: Pick one entity to consider" "3088": "Run the game and see that the mouse's rectangle is incorrectly placed and scaled" "3136": "handmade.cpp: Try doing Unproject without the subtract" "3172": "Run the game and see that it's surprisingly in the right place" "3263": "handmade.cpp: Consider the possibility that Unproject may be fundamentally busted" "3287": "handmade.cpp: Add OffsetP.z to LocalZ" "3309": "Run the game and suggest that that's more correct" "3419": "handmade_render_group.cpp: Study our routines" "3735": "handmade.cpp: Try putting that subtract back in to the Unproject" "3928": "Run the game and try to determine how far off we are" "3960": "handmade.cpp: Try hardcoding values" "4052": "Run the game and don't see a MouseP rectangle" "4100": "handmade.cpp: Pass WorldMouseP to PushRect" "4137": "Run the game and see that it's okay, but not great" "4157": "handmade.cpp: Set LocalZ to 1.0f" "4281": "handmade.cpp: Add RenderGroup->Transform.DistanceAboveTarget to PushRect" "4457": "handmade_render_group.cpp: Introduce CompleteUnproject" "4947": "Run the game and conclude that we'll want to clean up what's happening in the projection" "5029": "Q&A" "5058": "The lag is real" "5084": "How will the focal length factor in? Will you have FOV stuff?" "5163": "Elvin?" "5180": "Semi related: What do you think about using different types for Points and Vectors?" "5212": "Does the screen center need to be involved? It was used in CompleteUnproject" "5230": "Is part of the problem that the code isn't normalizing the motion between the mouse and the entity relative to the screen dimensions in world coordinates at the different levels?" "5283": "handmade.cpp: Try doing the MetersToPixels after the fact" "5323": "handmade_render_group.cpp: Check that there weren't any other transforms happening to PushRect" "5377": "Mm. We seem to have run out of questions" "5380": "What is the problem with this Unproject?" "5421": "handmade_render_group.cpp: Investigate the problem" "5546": "Meta-point: On the potential features of a development tool that would help with these types of problems" "5771": "Debugger: Inspect a bunch of values and copy them to a scratch buffer" "5972": "Owl of Shame Moment: We took out Z movement relative to the basis P" "6048": "handmade.cpp: Correctly set Transform.OffsetP" "6071": "Run the game and find it in the right place" "6257": "On getting bitten by a feature" "6279": "Lament this 2.5D nonsense" "6315": "Glimpse into the future and wrap it up" --- name: "day205" title: "Picking Entities with the Mouse" markers: "91": "Recap and set the stage for the day" "198": "handmade.cpp: Outline all of the entities" "285": "Consider making the renderer work more logically" "424": "handmade_render_group.cpp: Deprecate Unproject" "545": "handmade_render_group.cpp: Work CompleteUnproject into a new 3-dimentional Unproject function" "846": "win32_handmade.cpp: Unify our output and input coordinate systems" "1014": "handmade_render_group.cpp: Finish writing Unproject" "1061": "handmade_math.h: Introduce operator-= for vectors" "1099": "handmade.cpp: Call the new Unproject" "1130": "Debugger: Step in and inspect MouseP and PixelsXY" "1203": "handmade_render_group.cpp: Divide by MetersToPixels" "1216": "Debugger: Step back in to Unproject" "1469": "handmade_render_group.cpp: Look at the DistanceToPZ calculation in GetRenderEntityBasisP" "1522": "Blackboard: How DistanceToPZ is specified" "1674": "handmade_render_group.cpp: Rename ZMeters to ZMetersFromTargetPlane" "1709": "handmade.cpp: Set LocalZ = 3.0f" "1723": "Run the game and set that it now works" "1770": "handmade.cpp: Test to see if the MouseP is on the plane of the Entity" "1917": "Run the game and note that the scale is a little bit off" "1938": "handmade.cpp: Respecify Unproject to not take ZMetersFromTargetPlane" "2252": "Run the game and see that we're correctly doing that inversion" "2297": "Run the game and test how these outlines work" "2356": ""I guess the Wacom tablet decided to take its own life"" "2368": "handmade.h: TODO(casey): Real projections with solid concept of project/unproject" "2411": "handmade.cpp: Only push the outline when the mouse is over the entity" "2444": "handmade.cpp: Manually provide the ability to introspect the HOT_ELEMENT" "2792": "handmade_platform.h: #define all of these new DEBUG macros" "2854": "Run the game and see that we're still highlighting but that the debug menu no longer works" "2935": "handmade_debug.cpp: Unproject the MouseP" "2996": "handmade_render_group.cpp: Compute UnprojectXY" "3073": "Run the game and see that we have our picking back" "3111": "Q&A" "3195": "I'm a little unclear about what pressure is keeping you from doing the Z math exactly like you would in 3D" "3208": "Blackboard: Conceptualising Z" "3585": "Where are you going to draw the labels for entity properties?" "3605": "Did you decide which 'awesome thing' to do for tomorrow's stream?" "3625": "What do you define as a good game design?" "3634": "Curious if your decision to design your own game engine has more to do with you furthering your own skill level, or do you have reason to not trust the middleware solutions you have seen in the past?" "3882": "Did you play Warcraft III at all or any of the mods? I need some help replicating some of the movement mechanics from one of the games and nobody understands me when I describe it. Willing to pay PayPal to whoever can code it. I'm betting it's honestly somewhat simple" "3941": "Would it work to render it in full 3D and rotate all the sprites by 45 degrees (or whatever angle the camera is taking)?" "4071": "I understand the art is drawn in the 3/4 view. Is the camera at an angle or top down?" "4234": "The 3DS Zelda games do the 3D-at-an-angle for 2D" "4293": "So I'm making a full 3D RTS that uses a mouse with a joystick built in so you can adjust where you are looking with the joystick and still use the mouse as a mouse for unit selection. Do you think that is an untenable idea for a product? If you had to buy a new mouse for one game, would you be like "nooo"?" "4332": "Did you ever end up playing The Mother series? Still on your TODO?" "4349": "I kind of jumped over 100 episodes so I don't understand what the issue was with the debug selector. Was the issue with the hitbox depth only or also the position?" "4442": "Look forward to tomorrow's Devstreamathon and consider supporting Hitbox" "4513": "https://restream.io/" "4539": "Why did Jon get banned?" "4629": "Wrap it up" "4723": "Announcement: The speaker list for HandmadeCon 2015 will be announced on Monday" --- name: "day206" title: "Implementing Introspection" markers: "32": "Recap and set the stage for the day" "225": "simple_preprocessor.cpp: Introspection" "385": "simple_preprocessor.cpp: Name this function ReadEntireFileIntoMemoryAndNullTerminate" "436": "simple_preprocessor.cpp: Call this function to run on handmade_sim_region.h and build it up" "540": "build.bat: Add simple_preprocessor.cpp" "585": "Debugger: Step into simple_preprocessor.cpp and ensure that it works as expected" "651": "simple_preprocessor.cpp: Null terminate the file" "679": "handmade.h: #define introspect" "751": "handmade_sim_region.h: Use this introspect macro" "762": "Brown butter" "796": "Describe tokens" "898": "simple_preprocessor.cpp: Introduce token structures" "1001": "simple_preprocessor.cpp: Loop over the Tokens and print them out" "1218": "simple_preprocessor.cpp: Introduce struct tokenizer" "1280": "simple_preprocessor.cpp: Introduce EatAllWhitespace" "1389": "Get a little brained" "1686": "simple_preprocessor.cpp: Provide a way to parse identifiers" "1760": "simple_preprocessor.cpp: Move GetToken's functionality to the correct place and write EatAllWhitespace" "1873": "simple_preprocessor.cpp: Provide the ability to parse C-style comments and introduce IsEndOfLine" "2076": "simple_preprocessor.cpp: Introduce IsAlpha and IsNumeric" "2157": "simple_preprocessor.cpp: Handle unknown tokens" "2220": "simple_preprocessor.cpp: Skip the closing quote" "2327": "simple_preprocessor.cpp: Implement ParseIdentifier" "2409": "Debugger: Step into simple_preprocessor.cpp and inspect the Tokenizer" "2467": "simple_preprocessor.cpp: Handle skipping over the first character" "2553": "Debugger: Step back in and inspect the Token" "2610": "Run the preprocessor and look at its output" "2649": "simple_preprocessor.cpp: Introduce ParseIntrospectable" "2729": "simple_preprocessor.cpp: Introduce TokenEquals" "2888": "Debugger: Step in to TokenEquals" "2931": "simple_preprocessor.cpp: Check for the string "intr"" "2977": "Debugger: Step through the loop inspecting At and Index" "3051": "simple_preprocessor.cpp: Implement ParseIntrospectable" "3191": "simple_preprocessor.cpp: Introduce ParseIntrospectionParams" "3234": "simple_preprocessor.cpp: Introduce ParseStruct" "3317": "simple_preprocessor.cpp: Introduce ParseMember" "3364": "simple_preprocessor.cpp: Introduce RequireToken" "3419": "simple_preprocessor.cpp: Provide the ability to print out the DEBUG_VALUE" "3643": "Run the preprocessor and see what happens" "3715": "Q&A" "3772": "It seems like you are doing recursive descent parsing. Is that how you would describe it?" "3815": "Blackboard: Recursive Descent Parser" "3904": "simple_preprocessor.cpp: Introduce a more recursive example of ParseMember" "4157": "Can you please satisfy my C standard anal retention by accepting 'v' and 'f' as whitespace?" "4210": "Have you an opinion on OpenCLC? Would that be out of bounds for Handmade Hero?" "4231": "How would you handle errors if you were deep in the recursion? Is checking return values everywhere the best way?" "4278": "I showed up late. Can you explain what introspection is?" "4582": "Do you if Jon does "metaprogramming" for his language?" "4632": "Regarding errors again, would this be a place where exceptions would actually be useful?" "4680": "Now that we have the preprocessor, do you plan to make more use of it going forward in Handmade Hero?" "4698": "Who is Jon and what language are you talking about?" "4719": "I'm writing a parser that looks pretty similar to this, but it runs on multi-GB files which takes a while. Any common approaches to use SIMD/multithreading to speed up text parsing? Seems more difficult since the characters aren't "independent" in the way pixels are" "4818": "This stream makes me feel like an extremely inferior and incompetent programmer. Do you approve of this?" "4978": "How does metaprogramming change your workflow? Can you talk about incorporating generated code with the "regular" C files?" "5152": "Wrap up" --- name: "day207" title: "Using Introspection Data" markers: "106": "Recap and set the stage for the day" "246": "simple_preprocessor.cpp: On understanding the contents of structs" "451": "simple_preprocessor.cpp: Make ParseMember take StructTypeToken" "551": "Run the preprocessor and see this new information" "595": "build.bat: Pipe the output of the preprocessor to handmade_generated.h at compile time" "673": "Describe ths metaprogramming workflow" "700": "handmade.h: #include handmade_meta.h" "720": "handmade_meta.h: Introduce member_definition and meta_type" "828": "handmade_meta.cpp: #include handmade_generated.h and #include this file in handmade.cpp" "878": "handmade_generated.h: Mention the fact that once this is generated, we always have it" "919": "handmade_debug.cpp: Set some values and print them out using DEBUGTextLine" "1338": "Debugger: Run the game and see these debug values" "1395": "handmade_debug.cpp: Introduce DEBUGDumpStruct" "1498": "handmade_sim_region.h: Make sim_region introspected" "1546": "handmade_meta.h: Add the types in sim_region to meta_type" "1584": "handmade_debug.cpp: Set these values of sim_region and print them out" "1645": "Run the game and see the sim_region printing out" "1667": "handmade_generated.h: Note that new types have to keep being redefined in handmade_meta.h" "1708": "handmade_math.h: introspect rectangle2 and rectangle3" "1750": "simple_preprocessor.cpp: Process handmade_math.h" "1811": "Run the preprocessor and see that these rectangles are now defined" "1845": "handmade_debug.cpp: Show what we otherwise would have to do to define a new type" "1915": "Run the game and view those rectangles" "1928": "handmade_debug.cpp: Use the meta generator to define rectangle3 for us, and manually define MetaType_v3" "2147": "Run the game and see our debug output" "2158": "handmade_debug.cpp: Discuss ways to get this code generated for us" "2268": "simple_preprocessor.cpp: Introduce meta_struct to enable us to keep track of structs seen" "2511": "simple_preprocessor.cpp: Printout #define META_HANDLE_TYPE_DUMP and loop over the Meta structs" "2711": "simple_preprocessor.cpp: Take a look at how this injection works" "2761": "Run the game and see all of this new stuff being printed out" "2774": "handmade_debug.cpp: Add the concept of an indent level" "2930": ""There's nothing worse than a whiny C compiler"" "3089": "Run the game and see our newly indented output" "3112": "simple_preprocessor.cpp: Print a line to tell us what the member was" "3158": "Run the game and look over our generated debug information" "3200": "handmade_world.h: introspect world_position" "3287": "simple_preprocessor.cpp: Process handmade_world.h" "3302": "Run the game and see the entity printout" "3384": "handmade_sim_region.h: introspect everything" "3459": "Run the game and notice that pointers aren't handled correctly" "3516": "handmade_meta.h: Introduce member_definition_flag" "3554": "simple_preprocessor.cpp: Recognise pointers" "3586": "handmade_debug.cpp: Dereference a pointer and skip printing it if it's null" "3643": "Run the game and see it starting to make more sense" "3655": "handmade_debug.cpp: Set TestCollisionVolumeGroup parameters" "3781": "Run the game and see this information" "3793": "handmade_debug.cpp: Set another lot of values, but note that the generator does not know how to handle them" "3827": "handmade_sim_region.h and handmade.h: Introduce counted_pointer" "3883": "simple_preprocessor.cpp: Note that the parser must be aware of how to handle these counted pointers" "3920": "On building on our knowledge to progress from basic introspection to metaprogramming" "3984": "Q&A" "4042": "So when you say you've built up multiple layers of metaprogramming, do you mean your metaprograms output things like what we wrote today?" "4079": "Isn't offsetof fairly safe to rely on with remotely recent compilers?" "4106": "handmade.cpp: Try using offsetof" "4225": "Someone said that the string function you were looking for was called strdup" "4243": "In the episode of the Jeff and Casey Show "The Wolf Doesn't Want to Come Anymore" you mentioned that you use metaprogramming techniques to make up for modern language shortcomings. Curious what functionality you have used metaprogramming to achieve that you would have found prohibitive in modern languages? Can you suggest any specific usages to pursue for either program robustness, optimization, etc.?" "4345": "To rephrase, are your "multiply layered" metaprograms outputting further metaprograms? Or is it a single layer that has enough complexity to be considered more than a single pass? (Not sure how to phrase, I was mostly trying to prompt further discussion of what you've mentioned previously)" "4444": "Odd... offsetof is defined in MSVC's , and is specified in C '89 as belonging to that header... Did I miss something?" "4512": "Debugger: Use the test project to Go to Definition of offsetof" "4629": "Based on what Jonathan Blow has so far, do you think JAI will have the metaprogramming capabilities that you'd want? If not, what do you think it is missing?" "4703": "You said in a previous stream that you don't really program in C anymore, you basically program in "Caseylang". Does that refer to your metaprogramming tools or is there more to it than that?" "4718": "You're not using header files for OpenGL / Direct3D?" "4728": "Have you worked with any functional languages? Haskell or maybe Scala?" "4765": "Maybe a bit off topic but going along with the Master Spy thing, have you ever done a stealth game and, if so, what particular programming challenges do stealth mechanics bring that you don't usually have to deal with?" "4854": "Is the syntax of Casey-Lang still very close to C?" "4869": "Your metaprogramming tools sound very useful, will you ever open source them, maybe in your will if nothing else?" "4928": "Will you write your own installer for Handmade Hero? Or just zip it and be done with it?" "5004": "How about writing a Casey-Approved GUI debugger for Jai?" "5055": "I'm looking forward to additional visualizers in the debug view (e.g. a small grid view with a dot or line from (0,0) to represent a v2 along with the decimal digits). Do you think that would be worthwhile?" "5128": "Do you ever metaprogram the sims stuff and the job queue?" "5251": "Is there any feature you would add to Jai?" "5458": "Close it down" "5594": "Announcement: F2P discussion between Casey and Shawn McGrath on Thursday" --- name: "day208" title: "Adding Data Blocks to the Debug Log" markers: "97": "Run the game and recap our situation" "125": "handmade_debug.cpp: Get rid of the TestEntity stuff" "175": "handmade.cpp: Consider how we'd like to leverage metaprogramming" "666": "handmade_platform.h: Give DebugEvent the ability to output values" "974": "Run the game and see that the debug system does still work" "994": "handmade_platform.h: Compress the data" "1024": "handmade_sim_region.h: Consider manually defining the DEBUG_VALUEs to write to the debug stream" "1176": "handmade_platform.h: Conditionally #define the DEBUG macros differently" "1444": "handmade_platform.h: Introduce variations of DEBUGValueSetEventData" "1506": ""Not every infinity has to be huge"" "1765": "handmade_math.h: Move in the DEBUGValueSetEventData functions" "1791": "handmade_meta.h: Fix the definitions" "1907": "Debugger: Find that we are recording these debug values" "1944": "handmade_debug.cpp: Reassemble the debug variables back into a structured piece of data" "2307": "handmade_debug.cpp: Introduce DebugEvent_OpenDataBlock and DebugEvent_CloseDataBlock" "2492": "handmade_debug.h: Add them to debug_thread" "2602": "handmade_platform.h: Add them to debug_event_type" "2666": "handmade_platform.h: #define DEBUG_BEGIN_DATA_BLOCK" "2836": "handmade.cpp: Use StorageIndex for DEBUG_BEGIN_DATA_BLOCK" "3074": "handmade_platform.h: Add VecPtr to debug_event" "3149": "handmade_debug.cpp: Introduce AllocateOpenDebugBlock" "3290": "handmade_debug.cpp: Introduce DeallocateOpenDebugBlock" "3360": "Run the game and see that there's no change" "3380": "Q&A" "3418": "Great stream today! Could you explain how this code works? It's fast inverse square root, but I still have no clue how it works" "4067": "What would be a good project for a beginner game programmer?" "4123": "I just read that Natural Selection 2 (for which Unknown Worlds made their own game engine) say they no longer support Windows XP. Does Handmade Hero run on XP, and why wouldn't it?" "4345": "Have you used the Steam Controller? What do you think about it?" "4444": "Thanks, here was the blurb out NS2. Looks like a Visual Studio issue. (What else is new?)" "4485": "Numerical Methods that Work: this is the book you're recommending right?" "4552": "Q: Everything that runs on Windows P runs on Windows NP" "4587": "Any tips on reading books? I find it really hard to read them. I do enjoy their table of contents, gets me excited, but when I read on it gets quite boring" "4816": "Have you read "Linear Algebra Done Right?" by Sheldon Axler? I always recommend it to people who ask me about linear algebra" "4923": "On that note, how do you deal with some of the generally poor social skills in programming / math fields? Noticing this more and more lately, unfortunately" "5118": "Safely call it a day" "5195": "Announcement: F2P discussion between Casey and Shawn McGrath on Thursday" "5243": "Announcement: The speaker list for HandmadeCon 2015 will be announced next Monday" --- name: "day209" title: "Displaying Buffered Debug Data" markers: "53": "Adjust the chair" "106": "Recap where we left off" "217": "handmade_debug.cpp: Implement the various DebugEvents" "620": "handmade_debug.cpp: Introduce EventsMatch" "702": "handmade_platform.h: Massage debug_event" "800": "handmade_platform.h: Replace RecordDebugEventCommon with RecordDebugEvent" "845": "handmade_debug.cpp: Massage these DebugEvents" "880": "handmade_debug.cpp: Make DeallocateOpenDebugBlock take **FirstOpenBlock" "1069": "handmade_debug.cpp: Fix compile errors" "1145": "Run the game and see the same results" "1165": "handmade_debug_variables.h: Generate DEBUGAddVariables dynamically" "1624": "handmade_debug.cpp: Implement the variable adding stuff" "1785": "handmade_debug.cpp: Make DEBUGBeginVariableGroup take the DebugState" "1863": "handmade_debug.cpp: Rename DEBUGAddVariable to CollateCreateVariable and DEBUGBeginVariableGroup to CollateCreateVariableGroup" "1926": "handmade_debug.cpp: Introduce CollateAddVariableGroup" "1982": "handmade_debug.cpp: Bring DEBUGAddRootGroup into play" "2055": "handmade_debug.cpp: Massage DebugEvent_OpenDataBlock" "2250": ""Everyone is happy and smiling" (quote 280)" "2276": "handmade_debug.cpp: Introduce CollateCreateGroupedVariable" "2387": "Debugger: See what's getting passed to the DebugBlock" "2515": "handmade_debug.cpp: Correct typo" "2540": "Run the game and see that we're working" "2564": "handmade_debug.cpp: Provide a way to view the RootGroup per frame" "2655": "handmade_debug.cpp: Make DEBUGDrawMainMenu display everything expanded by default" "2721": "handmade_debug.cpp: Set debug_variable *Group = Tree->Group and conditionally override the Group" "2895": "Run the game and see what it's printing" "2935": "handmade_debug.cpp: Investigate why we're printing out so many RootGroups" "3090": "Debugger: Step into FirstOpenDataBlock to determine that our Events aren't matching and why" "3204": "handmade_platform.h: Consider removing the concept of EventsMatch" "3376": "Debugger: Run and find that we hit a first-chance exception when we wrap" "3412": "Debugger: Inspect the RootGroup" "3524": "Debugger: Step through RestartCollation" "3598": "handmade_debug.cpp: Test for HackyGroup" "3658": "handmade_debug.cpp: Provide the ability in CollateDebugRecords to break at frame 31" "3714": "Debugger: Step into CollateDebugRecords and inspect the data" "3831": "handmade_platform.h: Determine that we wrap the array when we hit frame 32" "3935": "handmade_debug.cpp: Make RestartCollation happen one frame earlier" "3966": "Run the game and see that the entity picker is working" "4004": "Q&A" "4109": "We've been on the debug code for quite a while. How much longer do you think it will take before we're finished?" "4293": "Do you ever use data breakpoints? I find them helpful when some value is changing somewhere but you're not sure where" "4399": "Does the design of this debug system differ significantly from the debug systems you've worked on for other games?" "4423": "(Not SUPER on topic, feel free to skip): How do you treat GL handles in your own code? Are they handled by the asset system or by something else?" "4470": "Call it" "4482": "Announcement: F2P discussion between Casey and Shawn McGrath after tomorrow's stream" --- name: "day210" title: "Consolidating Debug Data Storage" markers: "170": "Recap and set the stage for the day" "276": "handmade_platform.h and handmade_debug.h: Point out the repeated code that could be compressed out" "540": "handmade_debug.h: Make debug_variable contain debug_event Event" "641": "handmade_platform.h: Move the data from debug_variable to debug_event" "659": "handmade_platform.h: Make vectors and rectangles accessible as base types" "742": "handmade_platform.h: Port the DEBUGValueSetEventData functions to use our new base types" "794": "Anticipate mr4thdimention's editor 4coder" "859": "Compile and fix compile errors" "965": "Run the game and see that we're still passing the right values" "975": "Anecdote: Some of the most productive work you will ever do will be with the delete key" "1003": "handmade_debug.h: Consider deleting some code" "1058": "handmade_debug_variables.h: #if 0 as much of this code as possible" "1114": "Make this stuff not happen" "1134": "handmade_debug.cpp: Look at a secondary value when we see a DebugVariableType_Event" "1178": "handmade_debug.cpp: Use the debug_event_types from handmade_platform.h" "1357": "handmade_platform.h: TODO(casey): Have the meta-parser ignore its own #define" "1396": "handmade_debug.cpp: Make DEBUGBeginInteract and DEBUGEndInteract use the other information" "1610": "handmade_debug.cpp: Capture any DebugEvent as a data block" "1673": "Run the game and find that the Tree was never initialised" "1708": "handmade_debug.cpp: Check that the Group exists" "1736": "Run the game and see that it's all well and good" "1756": "handmade_platform.h: Recap the changes" "1786": "handmade_platform.h: Introduce DebugEvent_FirstUIType to contain the DebugVariableType_ data" "1909": "handmade_platform.h: Rename DebugEvent and DebugEventType to DebugType" "1986": "handmade_debug.h: Change debug_variable_type to debug_type" "2032": "handmade_debug.cpp: Rename plenty to DebugType" "2131": "Run the game and see that everything is still working as expected" "2168": "handmade_debug.h: Remove debug_profile_settings" "2229": "handmade_platform.h: Add BitmapID and SoundID to debug_event" "2280": "handmade_debug.h: Remove debug_bitmap_display" "2287": "handmade_platform.h: Add the type definitions for bitmap_id and sound_id" "2358": "handmade_platform.h and handmade_debug.cpp: Propagate BitmapID" "2455": "handmade.cpp: Output a bitmap to our debug system" "2538": "Run the game and see that we are outputting a bitmap" "2579": "handmade_debug.h: Note that the debug_variable is disappearing" "2673": "handmade_debug.h: Consider the possibility of debug_variable_link storing the VarGroup" "2806": "handmade_debug.h: Add *Children to debug_variable_link" "2908": "handmade_debug.h: Remove VarGroup from debug_variable and rename *Children to *ChildSentinel" "3076": "handmade_debug.h: Introduce debug_variable_group to contain the Sentinel" "3238": "handmade_debug.cpp: Propagate these new structs" "3558": "Debugger: Inspect Iter->Link" "3618": "handmade_debug.cpp: Read through the routine" "3695": "handmade_debug.cpp: Set the Link->Children" "3721": "Run the game and note that we're getting a little bit closer" "3760": "Q&A" "3802": "It's expected. I've got more to do?" "3846": "Why call it Sentinel instead of Head even though it is a sentinel?" "3881": "What's your favourite data structure?" "4017": "Handmade, I'm not sure if you specified this in a previous broadcast, but do you plan to implement side scrolling or any kind of platforming alongside the top-down view?" "4074": "Llvm is getting too deep?" "4100": "Legend of Zelda has some faux-sidescrolling rooms" "4123": "What has been your favourite thing so far writing this engine?" "4148": "I had an idea that's probably stupid. But I was wondering if a Vector that, when deleting an element, just left an empty spot that's skipped over when iterating, would still be cache friendly - and still efficient when deleting and inserting. This is slightly over my head though" "4287": "How about your favourite equation?" "4323": "Blackboard: Linear blend" "4346": "Do you use DirectX?" "4376": "What do you think of clang C1 for Visual Studio?" "4443": "If you were doing these compressions (the ones you did today) at work, how different would your process be?" "4551": "Microsoft is making clang for parsing -> intermediate a first class fully supported citizen for visual studio starting in November. Intermediate to machine is still Microsoft (C2)" "4633": "How long do you think it will take before someone makes a Linux debugger that can rival Visual Studios?" "4674": "What do you think of programming competitions? Have you participated in any?" "4688": "What role do you think software security has in modern gaming? Is it not worth wasting CPU cycles to guard against different exploits? How good of a job is the game industry doing in implementing it and should they be doing more or less?" "5015": "Close down the Q&A and get the chat link setup for Mr McGrath" --- name: "day211" title: "Removing Records and Translation Units from the Debug Code" markers: "65": "Recap where we left last time and set the stage for the day" "174": "handmade_debug_interface.h: Throw all of the debug annotation code into this new header file" "241": "handmade_debug.h: Remove debug_variable entirely and give its functionality to debug_event" "375": "handmade_debug.cpp: Rename DEBUGVariableToText to DEBUGEventToText" "390": "handmade_debug.cpp: Introduce GetName" "482": "handmade_debug.cpp: Replace Var->Event. with Event->" "490": ""Everyone's happy and fine and dancing around..."" "734": "handmade_debug_interface.h: Consider extending the concept of debug_event to support an additional Name and stop storing DebugRecordIndex" "910": "handmade_debug.cpp: Comment out Var->Name in CollateCreateVariable and ZeroStruct *Var" "945": "handmade_debug.cpp: Continue moving debug_variable functionality to debug_event" "1005": "Debugger: Notice that we don't currently support some of the DebugTypes" "1086": "handmade_debug.cpp: Assert that the Type != EndBlock" "1127": "handmade_debug_interface.h: Remove DebugType_FirstUIType from debug_type" "1159": "Run the game and see that it's all good" "1168": "handmade_debug_interface.h: Replace DebugRecordIndex with *Name and remove TranslationUnit from debug_event" "1343": "Pig Hat Time" "1351": "handmade_debug_interface.h: Stuff *FileName, *BlockName and LineNumber into debug_event and remove the concept of debug_record" "1705": ""Sometimes you're dumb"" "1734": "handmade_debug.cpp: Change Source to Event" "1840": "handmade_debug.h and .cpp: Change ScopeToRecord to be a char and change how it is used in DebugType_EndBlock" "1978": "handmade_debug.cpp: Remove GetRecordFrom" "2006": "handmade_debug.h: Add *Event to debug_frame_region" "2067": "handmade_debug.cpp: Set ColorIndex to OpeningEvent->BlockName" "2115": "handmade_debug.cpp: Rename Source to Event" "2126": "handmade_debug.cpp: Change HotRecord to HotEvent" "2170": "handmade_debug.cpp: Remove the check on GlobalDebugTable" "2185": "Run the game and see that we're getting a lot closer" "2220": "build.bat: Remove TRANSLATION_UNIT_INDEX" "2242": "Run the game and check that it's still okay" "2245": "handmade_debug_interface.h: Remove debug_record and put GetController back into handmade_platform.h" "2288": "handmade_debug_interface.h: Move ThreadID and CoreIndex from threadid_coreindex to debug_event" "2347": "Run the game and see that all is working nicely" "2359": "handmade_debug_interface.h: Remove #define MAX_DEBUG_TRANSLATION_UNITS" "2390": "handmade_optimized.cpp: Remove DebugRecords_Optimized_Count" "2408": "handmade_debug.cpp: Remove DebugRecords nonsense" "2434": "handmade_debug_interface.h: Consider packing debug_event a little more" "2538": "handmade_debug.cpp: Add Var->BlockName back in to CollateCreateVariable" "2562": "Run the game and see "Hot Entity" again" "2583": "handmade_debug.cpp: Remove debug_event *Var" "2646": "handmade_debug.cpp: Do CollateAddVariableGroup rather than CollateCreateGroupedVariable" "2710": "handmade_debug.h: Remove DebugType_VarGroup from debug_type and call it OpenDataBlock everywhere" "2755": "Debugger: Investigate why BeginBlock is happening" "2922": "handmade_debug.cpp: Remove CollateCreateGroupedVariable" "2928": "handmade_debug.cpp: Assert that Link->Event->Type != DebugType_BeginBlock in CollateAddVariableToGroup" "2954": "Debugger: Inspect Stack and Depth" "3034": "handmade_debug.cpp: Try doing RestartCollation on every frame" "3122": "Run the game and find that it was an overwriting problem" "3170": "Q&A" "3239": "Will you get back to game related coding next week?" "3274": "Do you ever wear the piggie hat at work?" "3297": "What would be the thing that would impress you on a programmer's resume?" "3332": "Bit off-topic, but when will you do the ODE stuff?" "3368": "Blackboard: Ordinary Differential Equation" "3562": "I think he meant e^kt" "3696": "I see a lot of branching in your code. Aren't you trashing the caches and the branch predictor?" "3916": "Been soaking up so much of this stream as I catch up. I realized that I'm writing the usage code first nowadays. It's really streamlined my implementation brain. Just wanted to say thanks. Debate was great too" "3935": "Been learning about x86 assembly in one of my CS classes. Is there any way to force the compiler to use a register for a certain variable instead of a place on the stack?" "4019": "Just asking, but is it worthwhile to put so much effort on the debug system at this stage? There's a lot of things you're doing right now that I'm not sure how it will help in the future (maybe just because I have never programmed games before), but if I as a newbie game programmer were to work on this, do you suggest going as far as you're going right now or proceed on the gaming part to see what I need first before doing it?" "4117": "Well if you would just replace the branches with polymorphism..." "4129": "What's more impressive: previous projects + practical experience vs college degree?" "4180": "Compilers generally ignore the 'register' keyword" "4254": "Ever thinking about running Handmade Hero through cachegrind?" "4385": "Wind it down" --- name: "day212" title: "Integrating Debug UI into Game Code" markers: "70": ""We will be in sync..."" "94": "Recap and set the stage for the day" "196": "Run the game and show that the picking system is kind of random and janky" "358": "handmade.cpp: Look at the current picking system and consider what we'd like to do" "554": "handmade.cpp: Decouple the hit testing and the output" "821": "handmade.cpp: Use debug_id in order to unify the system" "974": "On the uses of pointers as a location in memory and a name" "1224": "handmade.cpp: Make DEBUG_HIT take LocalMouseP.z" "1414": "handmade_debug_interface.h: #define the necessary values and implement them" "1771": "handmade.cpp: Introduce DEBUG_REQUESTED" "1850": "handmade_debug_interface.h: Give debug_event the concept of a DebugID" "1911": "handmade_debug.cpp: Introduce DEBUG_HIT, DEBUG_HIGHLIGHTED and DEBUG_REQUESTED" "1992": "handmade_debug.cpp: Check for the existence of Memory in DEBUGGetState" "2126": "Run the game and hit an assertion" "2254": "handmade_debug.cpp: Replace the Assert in DEBUGGetState with a check for DebugState" "2290": "Run the game and find that the debug system highlights everyone" "2309": "handmade_debug.h: Add DebugInteraction_Select to debug_interaction_type" "2385": "handmade_debug.cpp: Introduce DebugIDInteraction based on VarLinkInteraction which takes the Type and ID" "2507": "handmade_debug.h: Add debug_id SelectedID to debug_state" "2523": "handmade_debug.cpp: Write DEBUG_HIGHLIGHTED and DEBUG_REQUESTED" "2580": "handmade_debug.cpp: Introduce IsSelected" "2696": "Run the game see that it doesn't look very exciting" "2709": "handmade_debug.cpp: Clear the NextHotInteraction when we end" "2747": "Run the game and see that we're in much better shape" "2834": "Q&A" "2860": "You technically have 15 more minutes since we started late" "2905": "Use the 10 remaining minutes to nefarious ends" "2917": "handmade_debug_interface.h: Make DEBUG_HIGHLIGHTED take *Color" "2927": "On compiling something out and using ... as the parameters" "2957": "handmade_debug.cpp: Highlight entities in different colours" "3093": "Run the game and see that the picked entity persists" "3128": "handmade_debug.cpp: Make DEBUG_REQUESTED work on both the selected and hovered entities" "3180": "handmade_debug.h: Add SelectedIDCount to debug_state" "3212": "handmade_debug.cpp: Make IsSelected loop over all of the SelectedIDCounts" "3251": "handmade_debug.cpp: Introduce ClearSelection and AddToSelection" "3359": "handmade_debug.cpp: Make DebugInteraction_Select handle multiple selections" "3460": "Run the game and select as many things as we want" "3500": "Q&A Take #2" "3545": "<3. *handmade?" "3564": "You can emulate expression blocks with lambdas if you don't mind the craziness of C++11" "3584": "insobot checks for your !qa thing I believe, yeah" "3605": "Would you think it's better to start at a junior position at a company and then working my way up? Or try to apply for a higher position immediately?" "3623": "About universal IDs, what if some things want to be identified in the same system, but don't have fixed storage location or conflicts in some other way with the universal uniqueness?" "3710": "Do you know yet if the HandMadeCon talks are going to be streamed and / or recorded?" "3739": "Bots on bots... Damn, imagine all the off-by-one errors" "3747": "Yeah, but wouldn't bots teaching bots how to program be the beginning of the singularity?" "3756": "You have recommended The C Programming Language book after watching your introductory series. Are there any other books you would suggest such as proper programming practices or reference books?" "3785": "You mentioned that the pointer could be used as a key and the thing it's pointing to is the value. So do you mean something like this: PairOf X*, X?" "3805": "What else are you working on outside this project?" "3840": "If you're just starting to watch these videos and you don't have time to watch them all, which ones are most important?" "3909": "How do you pick apart code of other programs / websites, etc.? Sorry for the newbish spam, I just want to get started in the morning" "3993": "Trying to work with others and reading their code, do you try to understand everything they wrote or just understand enough to solve your problems?" "4080": "Is there a programming pattern you see all the time that you can't stand or hate?" "4182": "How do you deal with programming colleagues that use OOP, getters / setters, etc.? Do you try to give them advice or stay away from them if possible?" "4206": "I only know C++ really, but what's the alternative to getters / setters?" "4220": "Story: C++ getters / setters" "4510": "What about a getter than does some calculation on private variables? Like a getDay function on a class that stores an integer representation of time / date?" "4525": "Jon should do that for JAI" "4537": "C# does what you describe" "4572": "The getters and setters are less performant too, right?" "4581": "I know you mostly work on code in smaller groups of people, although what is it like to program in teams and how does the work get split?" "4630": "What about the downside that you don't know whether a value you're accessing does a function call or not?" "4675": "Wrap this up" "4706": "Announcement: The speaker list for HandmadeCon 2015 is up" --- name: "day213" title: "Turning Debug Switches into Events" markers: "91": "Recap and set the stage for the day" "178": "Select a bunch of entities and see our frame rate getting tanked" "235": "handmade_platform.h and win32_handmade.cpp: Implement modifier keys" "374": "Debugger: Go to Definition for VK_BROWSER_BACK" "491": "handmade_debug.cpp: Check to see that Shift is down in order to determine when to add to the selection" "533": "Run the game and try multi-selecting" "644": "Consider consolidating data from various sources" "730": "handmade_config.h: #if 0 everything and investigate how to handle erroneous settings" "860": "handmade_render_group.cpp: Introduce the concept of a DEBUG_IF to create the debug variables" "1152": "handmade_debug_interface.h: #define DEBUG_IF" "1500": "handmade_render_group.cpp: Use DEBUG_IF" "1706": "handmade_debug_interface.h: #define DEBUG_r32" "1829": "Anticipate Jonathan Blow's language JAI" "1911": "handmade_debug_interface.h: Rename variables to facilitate macros" "2789": "handmade_debug_interface.h: Add DebugType_Unknown" "2830": "handmade_debug.cpp: Continue cleaning up compile errors" "2904": "Anticipate mr4thdimention's editor 4coder" "3000": "handmade_debug_variables.h: Delete the file" "3053": "handmade_debug_interface.h: Implement the ability to compile out the entire debug system" "3809": "handmade_config.h: Manually rebuild the file" "3903": "Run the game and see that everything is working properly" "3929": "Q&A" "3943": "hmh_bot Clojure is a bad language" "3958": "Why use getkeystate() instead of WM_KEYDOWN / WM_KEYUP?" "4071": "I don't have much experience in it, but you mentioned the RTTI in C++ is not as good. Could you explain a bit why?" "4194": "I don't quite get why you need to nest the macros for DEBUG_IFs. Can you explain it?" "4598": "You mind going over your debug UI plan for those who don't know what the current plan is?" "4651": "Isn't metaprogramming a security hole?" "4660": "I've been reading about the cost of virtual functions. Normal non-virtual functions costs a 'call' command, but with virtual we need two fetches and a call. Is that very costly in performance critical areas? Is that the reason to avoid virtuals? For me, I don't like the fact that they introduce hidden costs, makes it harder to reason about your code" "4814": "I can't figure out for the life of me a way to draw an empty, non-filled Rectangle via the Win32 API. I tried SelectObject(DC, GetStockObject(NULL_BRUSH)) and then Rectangle(...) but it never draws anything" "4844": "win32_handmade.cpp: Demo MoveToEx and LineTo" "5067": "What are your thoughts on twitch starting to affect game design?" "5258": "Could you list the important features a good graphical debugger should have?" "5323": "Are you one of those that thinks that previously DirectX was better than OpenGL, but now is the opposite?" "5335": "Do you know how far has metaprogramming come along in other fields? I can imagine researchers using genetic algorithms to self enhance code" "5351": "Spin things down" --- name: "day214" title: "Collating Permanent Debug Values" markers: "85": "Recap and set the stage for the day" "125": "handmade_debug_interface.h: Turn on DEBUG_IF and resume implementing it" "253": "handmade_debug.cpp: Introduce DEBUGInitializeValue" "294": "Consider how to hook this into the system" "553": "handmade_debug.cpp: Make varieties of DEBUGInitializeValue for the various types" "767": "handmade_debug_interface.cpp: Try using the sequence operator to set DebugValue##Path" "1048": "On using the sequence operator to initialise a static" "1111": "handmade_debug_interface.cpp: Use the sequence operator to set DebugValue##Variable" "1191": "handmade_debug.cpp: Write DEBUGInitializeValue" "1307": "handmade_debug.cpp: Consider adding CollateAddVariableToGroup, AcquireMutex and ReleaseMutex to DEBUGInitializeValue to enable us to manipulate these types indirectly" "1527": ""A better way"" "1538": "handmade_debug_interface.h: Write a new, thread-safe DEBUGInitializeValue" "1850": "handmade_debug.cpp: Implement the ability to output all the variables in a list" "1902": "handmade_debug.cpp: Introduce GetGroupForName" "1927": "handmade_debug.cpp: "Double up on the fanciness"" "2013": "Blackboard: How handmade_config.h enables us to preload values on execution" "2115": "handmade_debug.cpp: Undo and introduce GetGroupForHierarchicalName" "2169": "handmade_debug.cpp: Add *ValuesGroup to debug_state" "2272": "handmade_debug.cpp: Make CollateAddVariableToGroup test if Permanent" "2326": "handmade_debug.cpp: Write GetGroupForHierarchicalName" "2489": "handmade_debug.cpp: Initialise DebugState->ValuesGroup" "2527": "Run the game and see that it picks up all the debug variables" "2542": "handmade_debug.cpp: Set *HackyGroup differently in DEBUGDrawMainMenu" "2568": "Run the game and see that we're sort of working" "2613": "handmade_debug.cpp and handmade_debug_interface.h: Investigate why we're adding the same variable multiple times" "2731": "Debugger: Break into DEBUGInitializeValue and inspect Event" "2882": "handmade_debug.cpp: Test if Event->Type == DebugType_MarkDebugValue at the start of the routine" "2992": "Run the game and see all of the variables" "3067": "win32_handmade.cpp: Reduce the number of threads used" "3130": "Run the game and see that we are still outputting too many copies of the variables" "3142": "win32_handmade.cpp: Revert the number of threads used" "3175": "Debugger: Break into DEBUG_IF and Go to Disassembly" "3321": "handmade_debug.cpp: Find that RestartCollation keeps rereading the events and adding them" "3537": "Q&A" "3563": "Variable initiation hack in DEBUG_IF macro makes my internal code quality kitten sad. Would it be possible to move that initiation to struct ""method""?" "3595": "Persisting the DEBUGValue between live code loading is great, I didn't understand what you were doing but then I got it with the demo, really cool. I had conflated the value of a variable with the value of debug of the variable. Small addition for a huge benefit" "3740": "Are you sad that you didn't fix Collation? If no more questions come in it would be neat to see it now, so you're not sad" "3769": "Will you have time tomorrow to look at 4coder? I am trying to decide whether to prioritize getting the new demo out tomorrow morning" "3873": "Gotcha, I do have parameterized commands that I'd love to hear a response on" "3910": "Why are you awesome? Which dojo did you train to become a code warrior?" "3942": "desuused elaborated with a Cmuratori prefix" "3979": "I quote "instead of writing debug_event Name = initiator((AnotherVar = something, something)); make a struct constructor debug_event (&AnotherVar, something) that initiates the value"" "4075": "So that you don't do assignment in the function call in the macro, which makes me really saaaad" "4225": "Are you playing any games? If so, what?" "4266": "So elvin = elxenoaizd?" "4298": "How did you keep up that awesome beat just now?" "4311": "What type of games do you prefer?" "4359": "Not elven but elzen" "4388": "Wind it down" --- name: "day215" title: "Cleaning Up Debug Event Collation" markers: "60": "Recap and set the stage for the day" "309": "Blackboard: The inconsistency between an event buffer and a frame" "585": "handmade_debug_interface.h: Start to make Events be a temporary buffer by reducing the MAX_DEBUG_EVENT_ARRAY_COUNT" "622": "Run the game, bump up the MAX_DEBUG_EVENT_ARRAY_COUNT and play with the camera" "686": "handmade_debug_interface.h: Remove MAX_DEBUG_EVENT_ARRAY_COUNT and MAX_DEBUG_EVENT_COUNT and bake their values straight into Events" "878": "handmade_debug.h: Start porting the rest of the code to use copy out" "1108": "handmade_debug.h: Reorganise debug_state" "1299": "handmade_debug.cpp: Massage DrawProfileIn" "1505": "handmade_debug.cpp: Replace the concept of CollateArena in GetDebugThread with allocatable values" "1648": "handmade.h: #define FREELIST_ALLOC" "1783": "handmade_debug.cpp: Use FREELIST_ALLOC in GetDebugThread" "1834": "Internet: decltype" "1871": "handmade.h: Fight with decltype" "2079": "handmade.h: Make FREELIST_ALLOC work" "2103": "handmade_debug.cpp: Introduce NewFrame to initialise the collation" "2568": "handmade_debug.cpp: Implement collation" "2753": "handmade_debug.cpp: Provide the ability to get new frames" "2900": "handmade_debug.cpp: Work through compile errors" "3420": "handmade_debug.cpp: Introduce FreeFrame" "3471": "handmade.h: Attempt to silence the "assignment within conditional expression" warning" "3545": "handmade_debug.cpp: Fix some copy pasta" "3603": "Run the game and run out of memory" "3620": "handmade_debug.cpp: Implement FreeFrame" "4088": "handmade_debug.cpp: Introduce FreeVariableGroup" "4136": "Run the game and see that we still hit the Arena->Size assertion" "4181": "handmade_debug_interface.h: Ensure that the debug system can be compiled out" "4241": "Run the game and see that we're back to our super speedy software rendered world" "4253": "Q&A" "4371": "Once collation is done, will we get hierarchies going next?" "4431": "Are you going to do some tricks for compile time string searches or something?" "4444": "The last software company I worked at, you would fail a code review MISERABLY right now. How do you feel about those practices?" "4592": "Do you use SQL and, if so, how do you structure your databases?" "4610": "I imagine that all the "paths" will be known at compile time, so you probably don't need to do strcmp but I'm not sure if just using the addresses would work" "4644": "By the way, I tried decltype() on clang and it worked in the same kind of context (I think). cl is probably broken" "4663": "Can you give us some programming challenges for until you get back?" "4702": "Would it be viable to write a game that uses a database model and its logic as database transformations?" "4842": "My mind cannot stop thinking about the scratch memory thing you talked with Jon the other day on the pre-stream, so I'm sorry if this is off-topic. It was a piece of memory that is kept per thread (and grows a little). Do I understand it correctly that you're passing it down the call stack, so that each function can push and pop a piece of scratch memory from it?" "4926": "I've never thought about metaprogramming much before, and it sounds really interesting. Do you have any recommendations for more information on it?" "4950": "What happens with the particles' (more simplified) collision detection if you at the same time hold and drag the window's title bar, since the game timer will be paused when the window is in the drag / size message loop built into Windows?" "5072": "How would you "abstract" a math library as in, the game / engine uses a v2 / v3 / v4 class and you have to use graphics libs with predefined vector classes they use for rendering but you don't want to couple your game with one of these libs?" "5127": "Close down" --- name: "day216" title: "On-demand Deallocation" markers: "34": "On easing the burden of returning to code after a break" "163": "Recap and set the stage for the day" "185": "build.bat: Turn the debug system back on and assess our situation" "268": "Run the game and note that the Last frame time looks weird" "341": "handmade_debug.cpp: Consider making FreeFrame work and be called" "475": "handmade_debug_interface.h: Talk through the debug system" "923": "handmade_debug.cpp: Consider looking at elements over multiple frames" "1235": "handmade_debug.cpp: Consider implementing FreeFrame" "1307": ""You'll have to excuse me if I yawn during this frame"" "1318": "handmade_debug.h: Look at debug_frame" "1433": "Blackboard: "Debug Element"" "1850": "handmade_debug_interface.h: Consider making the debug_table be a giant buffer" "2019": "Blackboard: Using a giant 64 MiB buffer" "2461": "handmade.h: Consider providing the ability to allocate memory on demand" "2577": "Yawn" "2625": "handmade.h: Pass the entire AllocationCode to FREELIST_ALLOCATE" "2800": "handmade_debug.cpp: Consider proving a way to free on demand or give memory_arena the ability to handle memory allocation" "2878": "handmade.h: Introduce ArenaHasRoomFor and GetEffectiveSizeFor" "3082": "handmade_debug.cpp: Introduce PushSizeWithDeallocation" "3408": "handmade_debug.cpp #define DebugPushStruct" "3444": "handmade.h: Fix compile errors" "3512": "handmade_debug.cpp: Replace PushStruct with DebugPushStruct" "3545": "handmade_debug.cpp: Pass the correct values to DebugPushStruct" "3588": "handmade_debug.cpp: #define DebugPushCopy" "3651": "handmade_debug.cpp: Continue fixing compile errors" "3683": "handmade_debug.cpp: #define DebugPushStruct and consider building in the Push functions to the arenas proper" "3772": "Compile and run the game, run out of memory and hit our "Not implemented"" "3828": "Q&A" "3855": "Have you heard of the DTrace tool? It allows dynamic tracing on running binaries and also kernel! (Not available on windows, though)" "3878": "You mentioned in the prestream a 'dynamic' memory_arena. How does that actually work since we allocate memory only once? What happens when the arena is full?" "3945": "You've mentioned the term "Collation" on this episode and several previous episodes. What exactly do you mean when you use that term?" "3997": "What keyboard do you use?" "4014": "Could you elaborate a bit more on what 'memory alignment' means?" "4117": "But wouldn't asking the OS for more memory expose more failure points thus be against Handmade Hero memory philosophy? Since the whole point of our scheme was that we're sure once we run the game we can't crash" "4239": "I'm always hesitant when using Linked Lists in engine and gameplay code (debug code is fine) because of their cache unfriendliness, random access of memory and difficulty in debugging (you'd have to dig down a node to find what you're looking for). Do you think it's not that big of a deal and I'm worrying too much?" "4502": "I'm debugging on Day 121. Do you used int instead of int32 for any reason?" "4524": "handmade.cpp and handmade_debug.cpp: Replace int with u32" "4616": "libs like the stb libs let you specify a custom malloc / free function. How would you integrate that into an arena-based system?" "4674": "Have you heard of VMem?" "4683": "If we wanted to use object pools (reusable / recyclable objects for enemies, for example), where would be the best place to store them? Permanent or transient memory? I guess they wouldn't be in transient cause the whole game shares the same pool, so I guess permanent?" "4734": "reinterpret_cast, static_cast and dynamic_cast: are they of any good use?" "4773": "There are libs that allow allocating and freeing multiple chunks of memory during runtime. How would you specify malloc / free for them in an arena-based game like Handmade Hero?" "4886": "The int use in question was a lot in SIMD'ing DrawRectangle -> DrawRectangleQuickly, and my version of the code is crashing on "Access violation reading location" when casting Pixel to __m128i at the start. Could iterating with int vs int32 be the reason?" "4931": "What do you think of pass by reference and references? I think they obfuscate the code because it's harder now to see from the calling site to find out if an object is passed by value (copy) or we are actually passing an address of it to modify it" "5147": "Wind it down" "5214": "Announcement: Handmade Hero Forums are now hosted on HandmadeDev.org" "5284": "Announcement: HandmadeCon 2015" --- name: "day217" title: "Per-element Debug Event Storage" markers: "154": "Run the game and hit our assertion in FreeVariableGroup" "229": "handmade_debug.h: Consider cleaning this stuff up as we do it" "322": "handmade_debug.h: Move RootGroup from debug_frame to debug_state" "428": "handmade_debug.h: Introduce debug_element to store a chain of Events" "594": "handmade_debug.h: Introduce debug_stored_event" "681": "handmade_debug.h: Provide a way to walk the existing debug elements and free them" "942": "handmade_debug.h: Add TotalFrameCount and calculate how long the debug system will then be able to run before the TotalFrameCount wraps around" "1122": "handmade_debug.cpp: #if 0 RegionIndex and work on VarLinkInteraction" "1371": "handmade_debug.cpp: Introduce GetEventFromLink" "1643": "handmade_debug_interface.h: Refresh our memory of DEBUGInitializeValue and RecordDebugEvent" "1895": ""Riddle me this, Batman"" "2129": "handmade_debug.h: Add ElementHash to debug_state and talk through the system" "2347": "handmade_debug.h: Add debug_tree *RootTree to debug_state" "2394": "handmade_debug.h: Reduce the size of the ElementHash array" "2479": "handmade_debug.cpp: Rewrite FreeFrame" "2788": "handmade_debug.h: Add debug_stored_event *FirstFreeStoredEvent to debug_state" "2824": "handmade_debug.cpp: Remove HackyGroup" "2983": "handmade_debug.cpp: Considering removing the concept of Region and sending all the BeginBlock and EndBlock into the ElementHash" "3048": "On coming towards a coherent architecture" "3166": "handmade_debug_interface.h: Figure out how to uniquely identify events" "3470": "handmade_debug_interface.h: Add GUID to RecordDebugEvent" "3556": "handmade_debug_interface.h: #define UniqueFileCounterString" "3682": "handmade_debug_interface.h: Remove FileName and LineNumber" "3714": "handmade_debug.cpp: Introduce HashThisEvent but turn off HANDMADE_INTERNAL" "3742": "Q&A" "3833": "For UI programming, what do you think of the MVC (Model View Controller) pattern? Is it of any practical use?" "4007": "Could you talk a bit about other debug system-y stuff you've done before? I've done all sorts of debug systems, not much like what you're doing now, and I'm curious what other stuff you may have done (just high level description, one-sentence descriptions are fine). Thanks!" "4273": "Can you explain what the macro-nastiness exactly does? Why do you have two underscore "levels"?" "4392": "Would you say that your engine makes it easy for a new programmer to come in and add functionality?" "4428": "I was implementing Shadow mapping in OpenGL. It seems that there's a lot of issues and artifacts: Shadow Acne, Peter Panning etc., and to work around those you end up with something more complex and expensive. I kind of find it hard to believe that games with decent graphics use this technique. Do you know of any other good way to implement shadows, or do we just have to work around its limitations?" "4745": "Is the mobile platform limit to Android-only (excluding iOS) for any particular reason?" "4821": "What if we just blur the edges of the shadows? (Gaussian blur)" "4863": "Do you think namespaces actually solve the problem of naming collisions? Or there's no need for them and the usual C-style 'SystemName_Function' suffices?" "4892": "Yes, but how is Windows any different, don't you need to compile Windows programs on Windows?" "5170": "On overcoming world hunger" "5222": "Close it down" --- name: "day218" title: "Hashing Debug Elements" markers: "80": "All You Can Eat" "110": ""We don't know which kind of a lunch buffet our debug system will be yet..."" "178": "Build and run and note how fast the guy zips around, before turning the debug system back on" "214": ""There will always a better lunch tomorrow"" "227": "handmade_debug_interface.h: Recap the GUID concept" "323": "On shifting the place settings when serving lunch" "353": "handmade_debug_interface.h: Pass in the GUID and make it work" "435": "Thoughts on the macro processor" "502": "On thinking about memory allocation over lunch" "580": ""It's more of a lunch thing"" "601": "handmade_debug.cpp: Make CollateDebugRecords put Elements into locations based on where they came from" "733": "handmade_debug.cpp: Introduce GetElementFromEvent" "964": "First Rule of Programming: "You don't eat lunch if you're already full"" "981": "handmade_debug.cpp: Continue implementing GetElementFromEvent" "1190": ""That's like getting lunch delivered..."" "1246": "handmade_debug.cpp: #if 0 CreateVariable, AddVariableToGroup, CreateVariableGroup and FreeVariableGroup" "1271": "handmade_debug.cpp: Introduce StoreEvent" "1434": ""Easy peasy lemon squeezy"" "1471": "handmade_debug.cpp: Continue working with the StoreEvent" "1558": "Thoughts on lunch despotism" "1584": "handmade_debug.cpp: Remove all of the Region stuff and #if 0 AddVariableToGroup" "1652": "handmade_debug.cpp: Implement StoreEvent" "1747": "handmade_debug.cpp: Fix compile errors" "1851": "Apologise for making a faux pas" "1860": "On the programming equivalent of sitting at the wrong seat at lunch" "1878": "handmade_debug.cpp: Vaporise PushSizeWithDeallocation" "1921": ""Don't let your whole life be defined by the one bad lunch you ate"" "1952": "handmade_debug.cpp: Make the StoredEvents be freed as necessary" "2218": "handmade_debug.cpp: Introduce FreeOldestFrame" "2376": "Compile, fix compile error and ensure everything else is doing something reasonable" "2414": "handmade_debug.cpp: Add if(ArenaHasRoomFor) to NewFrame" "2560": "handmade_debug.cpp: Make a PerFrameArena SubArena" "2684": "Debugger: Step into PushSize and discover that we didn't have enough debug memory" "2733": "Run the game and note that we're storing all of our debug data" "2785": "handmade_debug.cpp: Investigate why our Last frame time is wrong" "2890": "Debugger: Hit a FrameMarker and inspect values" "3006": "handmade_debug.cpp: Correctly set the MostRecentFrame" "3019": "Run the game and see that our Last frame time is now correct" "3032": "handmade_debug.cpp: Print out the memory usage of the arena" "3157": "Run the game and see our Per-frame arena space remaining" "3185": "handmade_debug.cpp: Reduce the size of that SubArena" "3221": "Run the game and see the new Per-frame arena space remaining" "3237": "Debugger: Step into StoreEvent and ensure that everything's still working properly" "3310": "Warn against eating more lunch than we can reasonably digest" "3343": ""There's always lunch tomorrow"" "3362": "Q&A" "3392": "When we come to do the AI system, do you think it'd be reasonable to give the dudes a "gather lunch" behaviour?" "3410": "What did you have for lunch?" "3444": "Imagine that you're young again and you're eating your lunch and you can choose between a C and Java-like language in what you can work with memory in much C-like way but that language would say you how to implement some ideas (like a Python is about line offsets, which is not good I think)? What would you choose then and why?" "3522": "During HandmadeCon will there be an organised lunch at the Campfire BBQ?" "3544": "Does Emacs offer more syntax support than what I am seeing at the moment?" "3576": "Is there anything that could be considered a "free lunch" in low level optimization?" "3587": "Fair warning: The optimizer might store the strings in the same place which will break the whole GUID thing" "3613": "Do you suggest programming should be snacked upon throughout the day as an alternative to a 3 course code feast?" "3748": "Why do you think that there have been no good new languages since C? Are all the language designers out to lunch these days?" "3853": "Do you feel there's a perfect balance between test-based coding, or more efficiency / optimization? Or do you prefer one over the other?" "3999": "What are your thoughts on clang?" "4051": "I think he meant string literals, like the -Og flag, I think" "4061": "What do you think about Unity, etc.?" "4189": "What's been the biggest hurdle you've had to overcome so far on this endeavor?" "4203": "What do you suggest that people who are in the first year of C++ do as projects for coding throughout the day? (Feel free to skip if you've answered this before)" "4281": "Have you seen John Cleese's talk on creativity? If so, what are your thoughts on it?" "4296": "How many more features will the debug system get? It already eats most other engines' lunch" "4345": "Do you feel that taking calculus 1/2 is needed to become a good programmer?" "4411": "It was actually the -GF flag for the MSVC compiler. It enables string pooling, lumping all string literals into a read-only portion of memory so it only stores one of each different string" "4482": "Do you think there really hasn't been a good language since C, period? Or just that there haven't been any good languages that do what C can, like a good "competitor"? For example, if someone needs a small app, use C regardless or some higher languages are good for that (in your opinion)?" "4560": "What if it doesn't pool strings and two same string literals get different addresses? Would the system lose its lunch?" "4626": "Pseudonym73: Note that "good language" is relative to what you're doing. I've done things in Prolog that I wouldn't want to do in C" "4814": "Wind down" "4954": ""Don't forget to eat lunch"" --- name: "day219" title: "Automatically Constructed Debug Hierarchies" markers: "2": "Intro" "31": "Background on the number 219" "70": ""You should fertilize that directory with human tears, and then you should see what grows from it. It will probably be black roses that crumble and blow away with the wind."" "99": ""The whole point of the existence of this system is because humans are so fallible and always do everything wrong."" "109": "Current state of the game when run" "124": "Brief explanation of unlimited debug info storage system from yesterday" "205": "Determining today's goal: bringing the debug system together" "271": "Starting work on hierarchical debug event UI" "292": "Describing how debug events should be grouped into a hierarchy of debug elements" "403": "Changing terminology of root tree back to root group" "443": "Re-enabling hierarchy generation for the new system" "518": "Considering whether or not to add free-list for the debug info" "565": "Updating AddVariableToGroup, CreateVariableGroup to work with elements in a tree hierarchy" "751": "Splitting AddVariableToGroup into AddElementToGroup and AddGroupToGroup" "829": "Noting names aren't stored in debug_variable_group, and fixing it" "941": "Removal of CreateVariable" "981": "Adding root variable group handling in GetGroupForHierarchicalName" "1057": "Creating root variable group" "1106": "Adding hierarchy lookup to GetElementFromEvent" "1165": "Thinking how BlockName and/or GUID should be used to create the hierarchy" "1334": "Use GetGroupForHierarchicalName when adding a new event to check for a parent group, and link them if there is one" "1423": "Enabling the drawing of the hierarchy" "1458": "Debugging crash due to not knowing how to draw certain debug elements" "1550": "Adding a default name for unhandled debug events to prevent crashing" "1569": "Running the game, now doesn't crash, but debug variables aren't listed" "1588": ""Sometimes even in the depths of despair, some little tiny thing goes your way, and the important thing to remember is not to let that go to your head"" "1619": "Start looking into why debug variables aren't appearing" "1791": ""I want to break down in tears. I want to just give up and let the horrors of the world continue unabated. But instead what I'm gonna do is set a breakpoint on MarkDebugValue"" "1809": "Add breakpoint to MarkDebugValue to see which events are getting through" "1846": "Explanation of the bug, partial fix by storing GUID in the event" "1909": "Rerunning the game, multiple events now correctly show up, but with incorrect text" "1917": "Storing BlockName into the event too, making the debug display slightly more correct" "2017": "Explaining how the debug names can be used to assemble the hierarchies" "2065": "Implementing the hierarchy building in GetGroupForHeirarchicalName" "2280": "Adding the GetOrCreateGroupWithName helper function" "2461": "Putting a name into the debug_variable_group struct, completing hierarchy creation code" "2643": "Adding a StringsAreEqual function with explicit length parameters" "2782": "Describing what more needs to be added for the debug hierarchy to display correctly" "2890": "Start branching the code to handle both single elements and hierarchies" "3099": "Running the game, now events are displayed hierarchically" "3233": "Adding interaction support to the hierarchical debug events" "3498": "Rewriting how groups are expanded" "3576": "Game running, interactions now working but with improper highlighting" "3703": "Debugging why multiple interactions are being highlighted as hot" "3731": "Found the bug" "3788": "Everything running correctly" "3825": "Q&A" "3851": "was this the 'depression oriented programming' approach i keep hearing about?" "3872": "you pass string length together with pointer to string data in several places. Do you think it would be better to create a string struct that holds length and a data point?" "3913": "You've talked a lot about languages lately, have you taken a look at Swift at all? Thoughts?" "3931": "How do you come up with that literacy stuff? That was Awesome! D" "3953": "I DONT GET ANYTHING :(" "3972": "do you think that the bug in DebugInteractionsAreEqual would have been caught by a compiler-generated comparison operator as in C++?" "4028": "will handmadehero2 be written in JAI ?" "4036": "I meant literature talk sorry lol" "4077": "Who is your favourite figure in the computing world (dead or alive)? Mine's currently Claude Shannon" "4099": "how about handmadebrowser in JAI? :)" "4120": "Off topic but how old were you when you started coding" "4127": "prestream question: do you think that intel hitting the proccesa size limit will make video game falter of will they survive?" "4173": "Casey, you are as old as me. Are you also planning to retire from working ASAP ? :-)" "4258": "What do you think about Test-Driven Development?" "4273": "do you actually play games yourself? If so what?" "4294": "Why should i keep on going in this harsh cold reality, when i get lost on episode 005 of hmh :(" "4342": ""We just have to have faith that The Variable is looking down on us from The Great Memory, and that if we all just work hard and try to be good people that eventually The Variable will let us into The Great Memory and we'll live in peace and happiness with all of our other discretized values."" "4377": "would you prefer to ui in c code or use something like html or something else?" "4388": "If you could be given complete control over Microsoft or Apple, which one would you choose and what would be your number one priority?" "4428": "Mind giving a shout-out about your appearance on the indie(Radio); podcast tomorrow? P" "4559": "Casey, the question was not entirely meant funny: Can you imagine to still code games and stuff when you are like 60?" "4615": "sometimes I compare myself with other great programmers and get depressed cause I'm far away from their level - I know I shouldn't be comparing cause they grew up in different environments etc and I know for sure I can reach their level if I apply myself and learn quick, but sometimes it just gets to me and I feel bad about it... have you ever felt that way? any tips how to overcome it?" "4990": "Do you think Japanese not adopting the OOP paradigm is because they are smarter or simply because of not even being interested in changing to new languages?" "5026": "Pseudo coder question: How would one go about learning Assembly language? And are compilers/linkers written in that?" "5172": "would you ever think about using C# or python?" "5187": "how do you approach getting an overview of a large code base, like clang or the linux kernel?" "5248": "Wind down" "5286": "Support episode guide extraordinaire Miblo" --- name: "day220" title: "Displaying Data Blocks in the Hierarchy" markers: "5": "Intro" "65": "Recap of the debug system" "142": "Ideas for today's work" "251": "Remembering how DEBUG_VALUE and DEBUG_BEGIN_DATA_BLOCK worked, considering unifying the unique IDs" "304": "Thoughts about using the string in BEGIN_DATA_BLOCK for debug UI layout" "350": "More thoughts on using EntityDebugID to differentiate entities without touching gameplay code" "393": "Recalling how debug data blocks work, and how they differ from the debug switches handled by the MarkDebugValue event type" "538": "Discussing the changes to debug data blocks that we want to implement, and how they'd help when debugging" "656": "Thinking about changing the allocation strategy of debug data blocks to match that of debug elements" "760": "An idea for unifying the debug data block + debug element code" "849": "Changes to the handling of the OpenDataBlock debug event type, to accommodate the new allocation idea" "897": "A quick look at how StoreEvent was working with debug elements" "932": "Clarification of how the debug system is currently working, and the planned changes" "1026": "Changes to the handling of the CloseDataBlock debug event type" "1051": "Updating the AllocateOpenDebugBlock function and open_debug_block struct to store a debug_element" "1127": "Allowing debug data blocks to override which debug_element StoreEvent stores into" "1164": "Actually using the right variable, running the game" "1175": "Removing erroneous quotes from the debug display by no longer passing strings to the DEBUG_BEGIN_DATA_BLOCK macro" "1199": "Running the game again, noticing a problem with a missing group, figuring out why" "1282": "Start trying to fix the debug data blocks not displaying as a group" "1352": "Adding a flag to GetGroupForHierarchicalName to optionally create an additional group" "1441": "Backtracking on the flag idea, deciding to directly turn the element into a group instead" "1507": "Verifying how the debug blocks work in the debugger" "1738": "Explaining how the workings shown in the debugger differ from what was expected" "1775": "Debugging GetGroupForHierarchicalName" "1971": "Gaining an understanding of the behaviour, explanation about how only debug_variable_groups have names" "2035": "Discussing potential solutions for getting the name passed in DEBUG_BEGIN_DATA_BLOCK to show up" "2071": "Choosing to store the OpenDataBlock event as well as the events for its contents, since it will contain the name" "2119": "Looking back at how the debug events are drawn, and adding a case for open debug data blocks (bitmap_id initially by mistake)" "2172": "Questioning why the erroneous change seemingly made a difference in output, figuring out why" "2219": "Back to thinking about why open data block names aren't showing up" "2251": "Adding a temporary change to the CloseDataBlock handling, which causes the data block endings to show up" "2283": "Adding some debug data block specific handling to DEBUGDrawMainMenu so the values inside the data block can be drawn" "2430": "Creating the DEBUGDrawElement and DEBUGDrawEvent functions to help in the drawing of debug information" "2538": "Talking about the complications of debug_events and debug_elements and how they both relate to the printing of debug info" "2580": "Changing DEBUGDrawElement to use debug_stored_event instead of debug_event so that it can walk through the next pointers" "2642": "Moving most code from DEBUGDrawElement into DEBUGDrawEvent" "2693": "Changing DEBUGDrawElement to extract the oldest event from the element, and determine if it needs to be forwarded to DEBUGDrawEvent or perform other work" "2818": "Fixing some compile errors by passing necessary variables to the new functions" "2844": "Adding the debug_tree to the layout struct and setting it in DEBUGDrawMainMenu" "2936": "Thinking about also adding the debug_variable_link to the layout struct, but choosing to re-factor the surrounding code to use debug_id instead" "3146": "Updating the interaction code, changing the function VarLinkInteraction to EventInteraction and passing the debug_id and debug_event instead of the debug_tree and debug_variable_link" "3251": "Removing the debug_tree from the layout struct since the interaction changes make it unnecessary" "3270": "Finishing off fixing the remaining compile errors" "3424": "Removing the now unused GetEventFromLink function" "3477": "Running the game" "3489": "Starting to add code to the DebugDrawElement function to loop through debug data blocks, and call DebugDrawEvent for each value held inside" "3530": "Changing DebugIDFromLink to DebugIDFromStoredEvent" "3575": "Adding a debug_tree argument to DEBUGDrawElement so that it can be passed to DebugIDFromStoredEvent, and finishing off its data block handling code" "3716": "Game running with the entity related data block now being added to the Simulation hierarchy" "3730": "Noticing problems related to the debug_id changing every frame for data block values" "3835": "Solving the problem by using event GUIDs to get stable debug_ids for data block values instead of the associated debug_stored_event address which wasn't stable" "3942": "Game running with the problem resolved" "4001": "Q&A" "4026": "What is the debug collator?" "4113": "https://hero.handmadedev.org/forum/code-discussion/902-day-211-gcc-clang-build-report" "4450": "How do game devs you work with typically handle temporary / non-shipping sound effects?" "4494": "Will there be a pass to strip unused code from HMH?" "4519": "What do you think about working in constraints and having limited resources? I think it makes programmers write less lousy code and force them to actually care and know what they're doing..." "4538": "Can we get rid of the build error (something about introspection of structs) that doesn't seem to affect anything?" "4711": "You missed Region->ColorIndex = (u16)OpeningEvent->BlockName;" "4749": "How many lines are we at now?" "4801": "Sure. What's a quick way to _produce_ temporary sound effects to, for example, figure out where/when they should be played?" "4876": "Not stripping unused code is how GTA Hot Coffee happened P" "5029": "If a programming job wasn't available to you, what type of work would you be interested in doing other than programming for a living?" "5050": "What do you think of dlc then? ;)" "5201": "Do you play MMOs, if so, how do you feel about the way they do their leveling?" "5212": "Wind down" --- name: "day221" title: "Implementing Multi-layer Cutscenes" markers: "48": "Assets: intro_art.hha is released" "183": "Introduce this art pack" "253": "handmade_file_formats.h: Add our new asset types and tags to asset_type_id and asset_tag_id" "308": "Blackboard: CutScene Art" "556": "Recompile and see that we're running as expected" "678": "Blackboard: Calculate how much space the cutscene requires" "721": "handmade.cpp: Increase the amount of memory allocated for the assets" "781": "handmade_cutscene.cpp: Start writing the cutscene code" "854": "handmade_cutscene.cpp: Introduce RenderCutScene" "1183": "handmade.cpp: #include "handmade_cutscene.cpp"" "1212": "handmade.cpp: Call RenderCutScene and introduce UpdateAndRenderGame" "1444": "Compile and run and hit an assertion in CheckArena" "1502": "handmade.cpp: Do EndTemporaryMemory before CheckArena" "1525": "Compile and confirm that this is now correct" "1540": "handmade.cpp: Toggle from UpdateAndRenderGame to RenderCutScene" "1566": "Debugger: Step into RenderCutScene and ensure we're getting a bitmap" "1618": "handmade_cutscene.cpp: Pass a height to PushBitmap and see the cutscene in action" "1640": "handmade_cutscene.cpp: Tweak the size and encounter a bug in the debug stuff" "1678": "build.bat: Turn off HANDMADE_INTERNAL" "1696": "handmade_cutscene.cpp: Tweak that size until the image fits the screen, and add layers to the scene" "1789": "What we did today" "1811": "Blackboard: Positioning the layers in space" "1932": "handmade.h: Introduce CutSceneTime" "1969": "handmade_cutscene.cpp: Pass CutSceneTime to RenderCutScene and slowly zoom the camera" "2260": "Run the game and see the cutscene in action" "2281": "build.bat: Temporarily compile in -O2" "2313": "Note that the image has no depth to it" "2346": "handmade_cutscene.cpp: Position the layers in Z based on their LayerIndex" "2443": "See the parallax effect" "2499": "handmade_cutscene.cpp: Work on the layers' positioning" "2579": "handmade_cutscene.cpp: Introduce LayerPlacement" "2678": "handmade_cutscene.cpp: Special-case the sky background" "2810": ""Hey, look! It did what I expected!" "2879": "handmade_cutscene.cpp: Place the layers" "3423": "Note that the only problem we have left is that we're zooming towards nothing" "3463": "handmade_cutscene.cpp: Introduce CameraOffset and set the focus point" "3631": "Q&A" "3691": "Would you normally want to get the position / scale for each layer from the artist? If so, how would you go about doing that?" "3799": "I am new to programming and know intermediate Java only. Can you explain what you use emacs for if you're using Visual Studio?" "3829": "I think you should move the skylight up a tad bit" "3850": "I feel like we should have some deep voice narration. "Down in the valley..."" "3871": "Did you ever have trouble while learning to program? I'm currently getting my rump handed to me in my Java class" "3929": "Will we ever load png files? If so, will we be writing our own loader or use stb_image.h? I read that it's tricky to load pngs or no?" "3954": "Will your cutscenes be coded like this, or be setup as data in a separate file?" "3981": "Do you need to know in-depth linear algebra to do this?" "4002": "You mentioned your codebase is mostly independent for the most part: does that include random number generation or do you use the C library for that?" "4032": "How do you handle 3D audio in your other engines and games? OpenAL or you implement something yourself?" "4077": "The sky-light just has a gap at the top was all" "4094": "handmade_cutscene.cpp: Move the sky light a touch closer" "4114": "Have you talked further with Pat Wyatt about coming on the stream, or is that postponed for when networking becomes relevant? I thought his talk was very interesting in particular" "4151": "Is this code going to be for a cinematic in the game or are you just testing the functionality now?" "4163": "Should I use uint32_t over u32?" "4179": "What do you think about adding lighting effects to the cutscene, like a flickering or pulsing of the candlelight in the welcome sign?" "4218": "I meant the image format before we pack them in asset. I understand we're currently using BMP" "4257": "For adding more cutscenes or modding, wouldn't it make more sense to keep the parallax constants somewhere in the hha file?" "4318": "Don't you need to link to user32, gdi32 and opengl32 for a few things?" "4352": "If you're writing OpenGL stuff, do you use GLEW or write your own extension loader and load the function pointers yourself?" "4361": "You could make a 2D VR game, just room with a giant video wall" "4376": "Off-topic: Thank you for HandmadeCon, I have watched it twice already" "4382": "Not a question. Just wanted to thank you for doing HandmadeCon! And glad to see you back doing Handmade Hero" "4424": "Any plans for crude lighting and shadow support for things like lightposts?" "4455": "Will you show all content creation on stream too? Watching you spend hours doing cutscenes might not be fun" "4572": "Out of interest, if you wanted to implement a zoom that curved to the contours of the hill (forward, drop, forward), would you still look to implement that in code or look at a visual tool for something like that?" "4681": "Thanks for the stream, Casey" "4686": "Did you have to study algorithms in depth or did you learn from on-hand experience?" "4761": "Is VSYNC part of the renderer? At least on my end on the stream there is quite a bit of tearing. Not sure if that is the stream or not" "4860": "Have any of the responses to your questions at HandmadeCon affected your approach to certain problems?" "4908": "Was the snowman intentionally looking down to indicate a feeling of sadness, or am I reading too much into it?" "4986": "Has a programming problem ever stumped you? Even after googling and or collaboration?" "5095": "That's a good quote" "5106": "On using metrics to determine which implementation is the most appropriate for a given situation" "5201": "When you were an intermediate programmer how often is it that you used Google to help you look up solutions to hard problems? Or do you always try to first approach it yourself?" "5218": "It may be obvious but there is an entire class of programmers that seem to think otherwise" "5232": "Did you notice the triforce in the windows?" "5263": "One of my mentors used to say that there should be a book called "Algorithms, Data Structures, and Tradeoffs"" "5281": "Wrap things up" --- name: "day222" title: "Laying Out Cutscenes" markers: "32": "Recap yesterday's work on the cutscene" "88": "handmade_cutscene.cpp: Introduce struct layered_scene to hold all of the cutscene data" "195": "handmade_cutscene.cpp: Introduce RenderLayeredScene" "265": "handmade_cutscene.cpp: Define the layered_scene" "367": "On solving the problem and then generalising from that, i.e. compression oriented programming" "425": "handmade_cutscene.cpp: Clean up a few things" "478": "handmade_cutscene.cpp: Introduce scene_layer and scene_layer_flags" "692": "Run the game and see our scene" "718": "handmade_cutscene.h: Move in our structs from handmade_cutscene.cpp" "754": "handmade_cutscene.cpp: Setup to compose further shots" "848": "handmade_cutscene.cpp: Encode the Z-movement in CameraStart and CameraEnd" "963": "handmade_cutscene.cpp: Compose Shot 2" "1284": "Missing snowflakes..." "1350": "handmade_cutscene.cpp: Compose Shot 3" "1545": "handmade_cutscene.h: Add CounterCameraX and CounterCameraY to scene_layer_flags" "1637": "Compile and see that everything should change, apparently" "1675": "handmade_cutscene.cpp: Do the Z-case" "1694": "handmade_cutscene.cpp: Continue composing Shot 3" "2649": "handmade_cutscene.cpp: Compose Shot 4" "2839": "Missing children" "2951": "On misplacing children" "3052": "handmade_cutscene.h: Add MinTime and MaxTime to scene_layer and Transient to scene_layer_flags" "3104": "handmade_cutscene.cpp: Set Transient layers" "3217": "Watch the animated version" "3251": "handmade_cutscene.cpp: Compose Shot 5" "3311": "The money shot" "3481": ""That is video games"" "3523": "handmade_cutscene.cpp: Compose Shot 6" "3573": "When Krampus comes into the picture" "3921": "Q&A" "3952": "Why not pass how long each cutscene is instead of it being the same for all cutscenes?" "3986": "For the weird camera movement scene what do you think about interpolating against a curve instead of linearly?" "4028": "Yangtian's art is awesome!" "4060": "Please do more" "4086": "handmade_cutscene.cpp: Compose Shot 7" "4256": "handmade_cutscene.cpp: Compose Shot 8" "4561": "handmade_cutscene.h: Add v2 Param to scene_layer" "4651": "handmade_cutscene.cpp: Continue composing Shot 8" "4824": "handmade_cutscene.cpp: Compose Shot 9" "5104": "Do you enjoy the screaming of the linker lamenting and writhing in Sisyphean agony that he can't write to the .exe?" "5121": "Do you have someone lined up for voice acting?" "5151": "The first scene with a glove it was a left hand glove and the next it's a right hand glove" "5235": "The door was open in the first scene but closed before Krampus enters" "5265": "Way back on Shot 2 I noticed a gap at the top of the window. Is that still there?" "5317": "Can I adopt one of the children?" "5333": "Try the community for voice acting? Quite a few of us would be willing / have good mics" "5352": "Will this game have support for left handed people?" "5377": "Could you explain the fading for animation" "5385": "Sorry to put you on the spot, but we didn't have anything special on 200th day. Anything planned for 256th?" "5395": "What's the best way to get my repo blessed on GitHub? I know it's kinda random, but the current blessed Rust repo hasn't been updated in 3 months" "5411": "You should add a little bit of snow on that one, to add depth" "5465": "We still need our own trig functions so we can stop sin()'ing by using the C standard library" "5538": "You mentioned earlier that we could make the animation sequence smoother by fading. For example when Santa put a hat on the hero. I was wondering what that would look like" "5561": "I noticed the cutscene bitmaps don't scale with the window size. Why is that?" "5588": "win32_handmade.cpp: Temporarily switch to using a smaller backbuffer" "5668": "Floor and Ceil are difficult?" "5739": "Why do we want to redo sin()?" "5837": "Call it a night" --- name: "day223" title: "Playing Multiple Cutscenes" markers: "32": "Recap" "71": "handmade_cutscene.cpp: Compose Shot 10" "349": ""...he has a lot of hats"" "806": "handmade_cutscene.cpp: Compose Shot 11" "1907": "handmade_cutscene.cpp: Introduce IntroCutscene to make these shots play in a series" "2265": "handmade_cutscene.cpp: Bust out that emacs macro" "2342": "handmade_cutscene.cpp: Set the ShotChangeTime" "2402": "handmade_cutscene.h: Add Duration to layered_scene" "2512": "handmade_cutscene.cpp: Give RenderCutscene the ability to play all of the shots in sequence" "2718": "Run the game and see that the cutscene isn't actually going" "2774": "handmade_cutscene.cpp: Set &IntroCutscene index from ShotIndex" "2797": "Debugger: Step into RenderCutscene" "2857": "handmade_cutscene.cpp: Introduce b32 PrettyStupid to indicate the end of the cutscene" "2888": "Run the game and see our cutscene happening" "3056": "Q&A" "3074": "Will there be hat DLC?" "3105": "Wait for more Q's" "3109": "Do you prefer OpenGL or DirectX?" "3128": "Who draws all the pictures?" "3134": "I think there is still a tiny gap at the top of the window in shot 2, towards the very end of the shot" "3185": "handmade_cutscene.cpp: Tweak the position of the window in Shot 2" "3235": "Seems like the cutscene is nearly finished (for a first pass). Are we returning to debugging next?" "3250": "How do you compile so fast?" "3260": "Will there be sound effects in the intro scene (i.e. door opening sound effects)? Would this be separate or part of the voiceover?" "3284": "I'm starting out Game Development and know a good portion of C++, but trying to learn OpenGL or advanced graphics rendering libs is feeling too tedious to me. Any recommendations?" "3346": "Will the hat be in the cut scene after it's chosen?" "3376": "Excited for Vulkan?" "3386": "Could we just watch the cutscene on loop while we do Q&A?" "3409": "Know any good OpenGL tutorials?" "3444": "For that over the shoulder scene, what if you could give the boy a velocity as well, so that it partially exaggerated or countered the camera movement, giving him some actual movement?" "3479": "What do you have to say to the anti global variable zealots who would complain about all those globals in the cutscene code?" "3516": "I think the last shot still has clipping at the end (the hero's head)" "3578": "What's your favorite header file to include? The ones you will add when starting a project" "3626": "One day you mentioned the banding on the stream overlays and said that it would be really easy to fix. How would you fix it?" "3682": "Who is your ideal 'voice of Krampus'?" "3694": "Do the hats bestow magical powers upon you?" "3702": "I asked this during the pre-stream, but not sure if you caught it. Still catching up with the series, but have you written a better hash after the sim region episodes?" "3727": "Off-topic - How much planning for a large (longer than one year) software project do you do before you start the project? How do you estimate the time it takes to get the work done?" "3779": "When is Vulkan coming out? Why do you not like Vulkan?" "3787": "Are you familiar with FreeGLUT? Thoughts on that specifically" "3800": "I'm trying to go as independent as I can in my codebase as well. One thing that I'm not sure how to replace is GLEW, i.e. how to load the OpenGL functions myself. You mentioned you had your own library for that. Any tips / advice how to write / where to begin?" "3847": "What Did Krampus do with other children after he gifted that hand to our hero? What was the purpose of his visit?" "3859": "Do you at least include windows?" "3869": "There's a glitch in the graphic near the cockroach's antenna in the hats plane" "3926": "I have a feeling the clip plane might have been introduced when we were doing the multiple ground layers" "3978": "Maybe on Day 107: Fading Z Layers" "4011": "Krampus sounds so cool. How did you come up with the name?" "4069": "Does Krampus return to 0?" "4115": "Thank you, Casey" "4138": "Will you be doing Ludum Dare this weekend?" "4208": "Sometimes the transition from scene to scene is not perfect. Are you going to fix that?" "4387": "Windows Task Manager: Check our memory usage" "4517": "Windows Task Manager: Check our CPU usage" "4689": "Why make the CPU do it?" "4814": "Cockroach confirmed for familiar DLC?" "4820": "Is there some interface to use for using the GPU?" "4830": "Is this the most in depth game you've created (i.e cut scenes, game engine and so on)?" "4844": "NearClipPlane was introduced on Day 108: Perspective Projection (thanks to insofaras's git-fu)" "4854": "Isn't GLSL and the DirectX shader language good for this?" "4879": "Would it be possible to access the GPU without a driver?" "4947": "Moving graphics on-screen, get the CPU to do other calculations" "5040": "Don't mean to cramp your style. I made some stuff BitBlting too" "5093": "And gamma correction!" "5122": "Does bi-linear filtering hold up in 3D?" "5179": "Handmade cut scene screensaver for Christmas?" "5199": "Yeah, as far as I can tell, you set the NearClipPlane pretty darn arbitrarily" "5220": "Call it day" --- name: "day224" title: "Prefetching Cutscene Layers" markers: "84": "Recap, run the game and point out an objectionable artifact" "194": "Debugger: Step into RenderCutScene and note the unset State of the Asset" "372": "handmade.cpp: Play the cutscene back at an artificially fast rate" "409": "handmade_cutscene.cpp: Introduce RenderCutsceneAtTime" "565": "handmade_cutscene.cpp: Do an additional RenderCutsceneAtTime in RenderCutscene, passing 0 as the RenderGroup in order to do a PrefetchBitmap" "709": "Run the cutscene and see how it works" "744": "Do you guys know why there's [a glitch] on the beginning one?" "803": "handmade_cutscene.cpp: Create an initial black Shot lasting 20 (artificially accelerated) seconds" "860": ""n{un,one}?"" "928": "Run the cutscene and see the delay" "977": "handmade.cpp: Play the cutscene back at the natural rate" "1040": "win32_handmade.cpp: ToggleFullscreen on and watch the result" "1104": "handmade_cutscene.cpp: #define CUTSCENE_WARMUP_SECONDS" "1135": "win32_handmade.cpp: Issue a Clear if the LayerCount == 0" "1211": "win32_handmade.cpp: Figure out why the flicker is happening" "1285": "Internet: VirtualAlloc" "1392": "Debugger: Step into Win32ResizeDIBSection and inspect Buffer->Memory" "1430": "Internet: GetStockObject function" "1557": "win32_handmade.cpp: Draw the window background with GetStockObject(BLACK_BRUSH)" "1572": "Run the cut scene and see that the startup experience is pretty nice" "1603": "win32_handmade.cpp: Create the window without it being visible" "1659": "Consider possible directions" "1808": "handmade.cpp: Toggle back to the game and illustrate the concept of the game getting started" "1941": "handmade.h: Provide the ability to switch between the cutscene and the game" "2009": "Run the game, join it and note the need to prefetch the game assets" "2074": "handmade.cpp: Introduce DeleteLowEntity to be called upon pressing Esc" "2288": "Run the game and try killing the hero" "2326": "handmade.cpp and handmade_platform.h: Provide the ability to exit the game" "2538": "Run the game and try exiting it" "2555": "handmade.cpp: Check to see if the Esc key WasPressed" "2624": "Run the game and test the exiting" "2639": "handmade_cutscene.h: Introduce struct playing_cutscene to formalise what the cutscene is doing" "2742": "handmade_cutscene.cpp: Introduce MakeIntroCutscene" "2837": "handmade_cutscene.cpp: Pass in the CutScene to RenderCutscene" "2961": "handmade.h: Initialise CurrentCutscene" "3056": "handmade_cutscene.cpp: Note that the cutscene will no longer be hot reloadable" "3119": "handmade_cutscene.cpp: AdvanceCutscene to allow multiple cutscenes" "3149": "Run the game, test our new functionality and consider making the cutscenes reset" "3280": "Q&A" "3317": "Would adding a BlockUntilLoaded style function be a good idea to make sure even slower computers have all layers loaded before the scene starts?" "3354": "handmade_cutscene.cpp: Turn off the prefetches" "3427": "handmade.cpp: Check for AllResourcesPresent before doing TiledRenderGroupToOutput" "3528": "Isn't there a way to clear the back buffer using SIMD?" "3561": "Will there be any animated cutscenes or just zooming shots?" "3579": "Can you do a cloc?" "3605": "Would it be possible to fade from the desktop to the game's initial black screen? Failing that, I think it'd be cool if we fade into the cut scene from the black, and then back to black when we quit the game" "3702": "win32_handmade.cpp: Introduce FadeOut" "3870": "Internet: UpdateLayeredWindow" "4615": "Shut it down" --- name: "day225" title: "Fading In and Out from the Windows Desktop" markers: "75": "Recap our current situation" "105": "Internet: SetLayeredWindowAttributes" "176": "win32_handmade.cpp: Create a fullscreen window that's transparent but black, and gradually increase its opacity" "301": "Run the game and see the fade-out" "315": "win32_handmade.cpp: Make the fade-out routine something that can be called incrementally" "564": "Run the game and see that nothing happens" "587": "win32_handmade.cpp: Defer calling ShowWindow until FadeAlpha is 1.0f" "838": "win32_handmade.cpp: Enable the timing loop" "853": "Run the game and see a slight flicker on the transition" "964": "Debugger: Step into ShowWindow" "1115": "win32_handmade.cpp: Try doing ToggleFullscreen after showing it, then try and force a repaint" "1239": "win32_handmade.cpp: Set WindowsAlpha = 255 and test if(IsWindowVisible)" "1652": "Debugger: Break into ShowWindow in SetFadeAlpha and see it's not getting called" "1703": "Spy++: Look at the Window Styles" "1868": "win32_handmade.cpp: Correct the FadingComplete / ShowingComplete tests" "1903": "Run the game and see that we don't have our glitch" "1955": "win32_handmade.cpp: Introduce dFadeAlpha to fade back to the desktop" "2295": "win32_handmade.h: Introduce win32_fader_state and win32_fader" "2437": "win32_handmade.cpp: Introduce UpdateFade" "2483": "win32_handmade.cpp: Make a little finite state machine for the fades" "2665": "win32_handmade.cpp: Briefly describe the finite state machine" "2705": "win32_handmade.h: Add Win32Fade_FadingGame to win32_fader_state" "2806": "win32_handmade.cpp: Introduce InitFader, BeginFadein and BeginFadeOut" "3217": "win32_handmade.cpp: Only do BeginFadeToDesktop if Win32Fade_Inactive" "3268": "Run the game and see that we're working properly" "3299": "Q&A" "3344": "Casey, you need one more state to wait for alpha-enabled window to show, because you might have the same bug when you fade to desktop" "3445": "Your fading setup seems overcomplicated to me. Why not just take a screenshot, blit that to the back buffer, and fade that? What platforms wouldn't that work for?" "3626": "Why are you using a second window for the fade in, instead of just fading in the main window?" "3726": "Wow, thank you for such a comprehensive A: to my Q:. That's exactly what I wanted! Another small one: Would it be possible to make bits of the window transparent, e.g. for the situation where some monstar has torn a hole in the game window, revealing the desktop beneath?" "3811": "Suppose you're Microsoft, but instead of wanting all of the money in the world you just want to make a living selling your OS. Do you think you could do that while providing a good way for users of your platform to debug the code that uses your API?" "3917": "Can you not unset the layered window flag after doing the fade?" "4035": "Wait, why can I Alt-PrintScreen to capture HDCP with windows but I can't take a screencap manually? I have lots of screenshots of my PS3 through the player via prntscrnt" "4133": "So this detour was all about startup and shutdown fades, but how would you implement fading in between in-game scenes? This shouldn't involve the Windows API, correct?" "4165": "handmade_cutscene.h: Add tFadeIn to layered_scene" "4235": "handmade_cutscene.cpp: Implement fade to black between cutscene shots" "4376": "Run the game and see that fade" "4407": "Note that the alpha must be gamma corrected" "4601": "We are out of time" --- name: "day226" title: "Handling Multiple Metagame Modes" markers: "3": "Intro, plans" "79": "Description of the 'meta-game' elements that Handmade Hero needs" "294": "Setting up, compiling and running the current state of the game" "381": "Choosing the first programming task for today" "450": "Reviewing the cut-scene code" "696": "Adding the concept of game modes" "872": "Adding a union to game_state to hold individual state for each game mode" "1014": "Changing UpdateAndRenderGame to dispatch to other functions based on the current game mode" "1293": "Modifying the cut-scene code to use the new game mode concept" "1537": "Begin implementing the switching between game modes" "1647": "Changing the WorldArena in the game_state to ModeArena, to be used by all game modes" "1774": "Determining how parameters will be passed to game modes when switching between them" "1863": "Letting the caller of SetGameMode do the initialization of the new mode, to avoid having to pass unnecessary parameters" "2020": "Creating an arena in the World struct, for exclusive use by the main World game mode, instead of having it use the arena in the game_state struct" "2146": "Exposing the SetGameMode function, and updating PlayIntroCutscene and PlayTitleScreen to use the ModeArena" "2178": "Making world based functions use the new world-specific arena" "2241": "Finish implementing the game mode switch statement in UpdateAndRenderGame" "2314": "Adding initialization code for the world-specific arena" "2466": "Re-organising the main World game code to be in functions specific to the new World game mode" "2641": "Running the game to see how the new code is working" "2702": "Separating out the persistent elements of game_state from those specific to the World game mode" "2903": "Moving things around to more appropriate files and to appease the compiler" "3239": "Changing many world-specific functions to work with a game_mode_world struct instead of the game_state struct" "3706": "Adjusting the creation of memory arenas in the initialization code" "3914": "Fixing the remaining compile errors" "4001": "Out of time, running the game with the world mode currently inaccessible until the cleanup work is completed at a later date" "4028": "Q&A" "4087": "How do the memory areas work?" "4111": "Well since no one's asking, have you heard about AMD open sourcing a lot of their GPU stuff?" "4188": "Should the world mode changing be prefetched like the cut-scenes changing?" "4221": "So by 'meta-game' do you mean like the pre-game stuff?" "4231": "Hi! I just finished my first semester of computer science in school! Just learned some basic Java, but I was wondering on if you have any tips moving forward. Also, do you know of any colleges that have good computer science departments?" "4278": "Sorry slow night, the chat erupted into a flame war over the exclusion of option menus in games :-P" "4296": "I wonder if there's a specific reason you put the 3 game_mode structs into a union?" "4308": "So I have this generic USB controller that's not being detected by XInput, any ideas how to go about detecting it? Use DirectInput? Or try to use an Xbox controller emulator or something?" "4373": "Wrap up" --- name: "day227" title: "Switching Between Metagame Modes" markers: "7": "Intro" "102": "Plans for today" "160": "Looking back at what was achieved yesterday" "204": "Taking a detour to fix the zooming in a shot of the opening cut-scene" "439": "Restating how the mode switching should work" "568": "Final tweaks to the zooming" "676": "Adding input handling to the cut-scene and title-screen game modes" "1098": "Adding a loop to the game mode dispatch, to allow updating/rendering to be re-ran immediately by the new mode, if a mode switch occurs" "1222": "Moving original input handling code into the world game mode" "1275": "Fixing resulting compile errors and header file include order" "1468": "Making the world game mode switch back to the cut-scene mode when no heroes exist" "1578": "Debugging the new code" "1665": "Thinking about how the new mode switching code might interact with multi-threading" "1761": "Changing how the world is initialized" "1898": "Debugging why the world doesn't appear to fit in the arena" "2061": "Fixing the world game mode immediately exiting back to the cut-scene" "2243": "Running the game. It can now enter the game mode but there are still a few bugs remaining" "2297": "Fixing inability to move by re-enabling code that was #if 0'd yesterday" "2433": "Fixing the lack of camera following by making sure the arena is zero-initialized" "2658": "Running the game again with the bugs fixed" "2687": "Commenting on the previously mentioned potential threading issues with the mode switching" "2908": "Implementing a basic version of the title-screen" "3180": "Testing the title-screen code" "3224": "Quickly debugging and fixing a cut-scene crash related to mode switching" "3329": "Game running with all 3 game modes working as intended" "3400": "Q&A" "3417": "Could you leverage your debug code when trying to find the right values you want for the intro cutscene in realtime instead of recompiling?" "3440": "Add some credits and boom! We're done!" "3457": "How do you terminate or end each thread at the end?" "3475": "What are your thoughts on twitch asking you to switch labels to creative?" "3517": "Will we be reimplementing the profiler?" "3538": "The end of the executable" "3599": "Could you re-explain why you couldn't move the hero after cutscenes for a while?" "3616": "If someone wants to run your game in fullscreen but at a different resolution than native, how would they change it? You've said before you don't like menus, so would you use a launcher instead or something for those options?" "3795": "Could you do some resolution detection at startup to avoid starting at a broken resolution?" "3886": "You say "normal person" as if tech savvy people is something awful." "4024": "Talking more about resolution / 4K" "4124": "Do you generally do cutscene code before gameplay code when you're working on a game?" "4352": "Are we in a point where we're close to have to need to implement mixins?" "4373": "Will c++17 modules solve the #include dependency problem?" "4551": "Wrap up, episode guide info" --- name: "day228" title: "Waiting for Dependent Tasks on Metagame Mode Changes" markers: "13": "Gift Received in the Mail: Owl of Shame Baby" "126": "Recap and set the stage for the day" "314": "Describe a threading bug in tasks which access the game's mode state and which persist" "473": "Set out our choices for fixing this bug" "683": "handmade.h: Add b32 DependsOnGameMode to task_with_memory" "810": "handmade.cpp: Add Platform.CompleteAllWork and NeedToWait to SetGameMode" "1210": "Run the game and see that it does work right" "1233": "handmade_world_mode.cpp: Call PlayTitleScreen upon exiting from the game" "1263": "Debugger: Note that we may now be clearing a large block of memory to zero, run the game and use Debug->Break All to confirm that" "1386": "handmade.h: Introduce struct arena_push_params and inline arena_push_params in order to specify to the Push routines whether or not to clear to zero" "1634": "handmade.h: Introduce AlignNoClear and Align" "1791": "Propagate our new features to all of the Push calls that require it" "2138": "handmade.h: Introduce NoClear and finish writing these new functions" "2248": "Run the game and see that it runs much more snappily" "2281": "Consider making the memory arenas flow all the way down to the operating system level, making the debug system use a separate set of growable memory, and fixing the renderer's sorting" "2460": "handmade_render_group.cpp: Take a look at how the renderer currently works" "2612": "handmade_render_group.cpp: Consider removing the notion of the scanlines" "2661": "build.bat: Turn on HANDMADE_INTERNAL" "2697": "Run the game and watch our last frame time" "2776": "handmade_render_group.cpp: Remove the Even / Odd notion" "2869": "Run the game and enjoy our beautiful rendering" "2892": "handmade_optimized.cpp: Increment the Y counter by 1 rather than 2" "2953": "Run the game and see that we may have got a little faster" "2992": "handmade_render_group.cpp: Consider providing some way of knowing what we're sorting" "3191": "handmade_render_group.h: Add PushBufferElementCount to render_group to let us know how many elements have been pushed" "3327": "handmade_render_group.cpp: Introduce struct tile_sort_entry and use it in RenderGroupToOutput" "3655": "Run the game and see that it still works fine" "3691": "Q&A" "3726": "Could you tell us roughly how the expanding arena would be implemented?" "3777": "Is the lower level memory arena thing you mentioned for PC basically just what malloc / VirtualAlloc does?" "3805": "I got the K & R book to learn C. Any other useful resources? I take online stuff with a grain of salt" "3816": "Is interlaced the same as interleaved?" "3873": "What should I do with my life while Handmade Hero is on break?" "3906": "Which algorithm do you plan on using for sorting?" "3943": "Why are we running in a windows application (using WinMain) instead of a console one (using regular main(int, char**)), and still RegisterClass, CreateWindow, etc?" "3995": "Why was the interleaving added in the first place?" "4021": "How many TODOs are there in the code now?" "4049": "Is there much overhead to spawning the render threads every frame instead of keeping them around" "4065": "Do you always start with software rendering when working on games?" "4107": "For new year's can we get a marathon?" "4113": "Can you do really smooth animation in GDI, without vsync?" "4156": "Simple question, but how do you forward declare a struct in pure C? If I have "typedef struct foo {...} foo;" how do I forward declare this? I tried typedef struct foo foo; but it didn't work" "4189": "Do you have any optimization for not blending transparent pixels?" "4278": "Once you have sorting implemented, do you think you will change the renderer to draw front to back?" "4300": "Thanks, I was just curious in my console question. But sometimes I write utils that I would like to live in the background and not be visible on the screen, so I use a Windows application and hide the window. Is there any way to use a console instead and hide that (from taskmgr, etc.)?" "4328": "Can you give a quick overview of the way memory is managed at the moment? PushArena / BeginTempArena, etc?" "4366": "Blackboard: Memory Arenas" "4461": "Are you still using .bat file compilations?" "4485": "Wrap it up" --- name: "day229" title: "Sorting Render Elements" markers: "25": "Recap and set the stage for the day" "88": "Run the game and hit an assertion" "153": "handmade_world_mode.cpp: Turn off FillGroundChunk" "187": "Run the game and note the lack of sprite sorting" "274": "handmade_world_mode.cpp: Turn FillGroundChunk back on and note that we need some room in which to do the sorting" "329": "Debugger: Step into AllocateRenderGroup" "405": "handmade.cpp: Increase the amount of memory allocated to this TranState" "424": "Debugger: Step into BeginRender and inspect Work->Task->Arena" "483": "handmade_world_mode.cpp: Make RenderGroup use 512KB" "639": "Blackboard: Render Sorting" "836": "Blackboard: Sort buffer" "912": "Blackboard: Producing the sort key" "1141": ""For the love of god, Mischief"" "1203": "handmade_render_group.cpp: Consider how to sort" "1329": "handmade_render_group.cpp: Find the PushBufferOffset for each Entry in RenderGroupToOutput, and make the function take SortEntryCount and *SortEntries" "1529": "Blackboard: How we're currently rendering the screen" "1585": "Consider how best to do this sort" "1717": "handmade_render_group.h: Add u32 SortEntryAt to render_group" "1743": "handmade_render_group.cpp: Set that SortEntryAt in AllocateRenderGroup and use it in PushRenderElement_" "1816": "Blackboard: Pushing entries on from the top and sorts on from the bottom" "1857": "handmade_render_group.cpp: Implement these pushes, and make PushRenderElement_ take r32 SortKey" "1991": "handmade_render_group.cpp: Clean up compile errors and propagate the SortKey" "2319": "Run the game and see that it isn't quite right" "2380": "handmade_render_group.cpp: Reverse the sorting order" "2409": "Run the game and see that it is now correct" "2420": "Blackboard: The Clear was happening last, after rendering everything" "2465": "handmade_render_group.cpp: Introduce SortEntries" "2593": "Blackboard: Bubble Sort" "2856": "handmade_render_group.cpp: Implement SortEntries as a Bubble Sort" "3047": "Run the game and see that it might actually be right" "3111": "handmade_world_mode.cpp: Give the GroundBuffer some zBias" "3168": "handmade_world_mode.cpp: Turn off the GroundBuffer for now" "3188": "Run the game and see that the sorting is working properly" "3239": "handmade_world_mode.cpp: Increase the zBias and then apply the bias in the correct place" "3360": "Run the game and see that it all works correctly now (apart from the torso being in front all the time)" "3388": "Q&A" "3440": "Do you know the Vulkan release date?" "3476": "Well?" "3489": "Can you talk about pros and cons of heapsort and quicksort, and / or explain quaternions?" "3543": "Which sort are you planning to ultimately replace bubble sort with?" "3599": "Bubble Sort is the simplest sort? I worked my way to doing a Selection Sort in my practices, so assume that must be down there for simplicity" "3641": "n^2 is actually faster in most cases?" "3741": "Can't you just use binary insertion to put items into their correct position so the array is sorted the whole time? That way RenderGroupToOutput doesn't have to do anything" "3775": "Blackboard: Sorting After vs Sorting During" "3931": "Have you ever made something of this sort of a project before? When you stream, do you just do everything as you go, sort of "improv" coding, or do you do stuff off stream to prepare what you are actually going to code on stream?" "4027": "Are we going raid Shawn McGrath's stream tomorrow night after this one?" "4051": "How do you disable syntax highlight in Emacs while keeping comment and macro highlighted?" "4130": "Is your Visual Studio "custom" theme anywhere? I really like it" "4194": "Wrap it up" "4280": "Shout out to HandmadeDev, who are building a community site for projects like Handmade Hero, with nicer forums" --- name: "day230" title: "Refining Renderer Sort Keys" markers: "7": "Recap and set the stage for the day" "85": "Blackboard: Sort Key for Rendering" "366": "Blackboard: Treating Z purely semantically" "600": "handmade_world_mode.cpp: Disable the GroundBuffer, run the game and demo the situation with rendering entities on stairwells" "806": "Blackboard: On rendering entities on stairwells" "1062": "Unexpectedly hit an InvalidCodePath" "1123": "Debugger: Realise that we never reset SortEntryAt" "1154": "handmade_render_group: Introduce ClearRenderValues" "1427": "Run the game and watch the last frame time" "1498": "handmade_render_group.cpp: Consider how best to generate the SortKey" "1635": "handmade_render_group.h: Add b32 Upright to render_transform" "1686": ""Move this out to its own thang"" "1721": "handmade_render_group.cpp: Use Upright in the SortKey computation" "1828": "handmade_world_mode.cpp: Set the GroupBuffer to not be Upright" "1861": "Run the game and note that we don't leave a hole for the stairwells" "1948": "Try getting the stairwell thing working a little bit" "2028": "Run the game and note some rendering problems" "2098": "handmade_world_mode.cpp: Give the GroundBuffer some Z" "2187": "Run the game and find that the topmost GroundChunk now occludes everything, as expected" "2232": "handmade_world_mode.cpp: Get FadeTopStart to happen again" "2319": "Run the game and see that everything seems to be rendering properly" "2395": "Note that we're drawing the entire screen many times" "2488": "win32_handmade.cpp: Drop down the resolution to 960x540" "2588": "handmade_render_group.h: Separate the transform data into object_transform and camera_transform" "2718": "handmade_render_group.h: Introduce DefaultUprightTransform and DefaultFlatTransform" "2819": "handmade_render_group.cpp and handmade_debug.cpp: Propagate these changes" "3591": "Run the game and find that everything is exactly the same" "3644": "Q&A" "3685": "Brace yourself" "3713": "What is your preferred sorting method?" "3813": "Hi Casey. I'm currently working on an OpenGL framework for games. Wanted to ask whether I can use the code up to Day 023 (Live Code Editing), with the intend of making a commercial game eventually with it. Might be important to note that I'm also streaming, so the code might be visible sometimes when I stream framework development" "3838": "I know you said you really like discriminated unions, but how do you deal with managing the big case switch they may cause? That is usually handled by the OOP model by delegating to the object" "3936": "Demo: Switch statement vs dispatch" "4122": "Obviously we lost some performance over the last couple streams. Are you planning to try to optimize it back down, or just leave the software renderer as is and move into GPU rendering?" "4174": "A lot of the times when you develop something, you write it in the simplest way that just works, then you polish it to something good and more finished (e.g. what you did with dsound). For someone catching up, do you think it's good enough to just study and focus on that better version, or is there a value in writing that initial version ourselves?" "4247": "Hey Casey! I just found your series and was amazed that you are creating an entire game without using an external library like SDL (from what your episode one said, at least). I really wanted to watch your progress through the series but I have no Idea where to start in the 200+ episodes since I already am working on an SDL OpenGL game. What is your suggestion?" "4309": "I can't remember if you discussed this when it first cropped up but, when you are halfway up the stairs and blending the trees, you get a darker area where they overlap. What's the "fix" for that?" "4338": "Blackboard: On the need for compositing in order to fade" "4410": "Is std::qsort worth using compared to rolling your own?" "4464": "How do / would you deal with collisions between multiple entities in terms of collision resolution, not detection, like deciding how to resolve conflicts between multiple moving things? I kinda hit a wall there not seeing solutions that aren't very ugly (especially movement-order dependency)" "4588": "You said the scaling value is not used, but the camera transforms everything. What is the difference?" "4664": "What keyboard are you using these days? I know you're a connoisseur, so I'd love to hear a recommendation" "4706": "How would a front-to-back renderer actually work? Would it test every pixel before writing to it?" "4797": "Does multiple dispatch come up for you much (as in n types with n^2 branches)? How do you handle it when it does?" "4890": "Would you rather have an explicit fall-through statement with implicit break, instead of standard switch-statements? Seems much cleaner to me, or am I missing something?" "4961": "That's what I was afraid of but thought maybe you had some trick like a messed up precomputed alpha" "4997": "I know we just got over the holiday break, but will there be a break in Handmade Hero when The Witness launches? If it's a possibility, it might be better to ask the community if they want that" "5016": "Are you productive / feel good at programming no matter how many hours you work per week?" "5081": "Close up shop and glimpse into the future" --- name: "day231" title: "Order Notation" markers: "63": "Set the stage for the day" "177": "Blackboard: Order Notation" "253": "Blackboard: "unit"" "350": "Blackboard: Linear "scale", e.g. stamping envelopes" "519": "Blackboard: Nonlinear "scale", e.g. checking if any envelopes are addressed to the same person" "842": "Blackboard: Why we care about linearity" "957": "Blackboard: How this determines scalability" "1080": "Blackboard: Why we don't care about the constant when considering an algorithm's scalability" "1282": "Blackboard: How this translates into code" "1417": "Blackboard: Big O notation indicates "worst-case running time"" "1609": "Blackboard: "randomized algorithms"" "1714": "Blackboard: P (polynomial) vs NP (nondeterministic polynomial)" "2150": "Blackboard: On classifying problems as P or NP, e.g. "Boolean satisfiability problem"" "2445": "Blackboard: "NP-completeness"" "2712": "Blackboard: *Gotcha! e.g. "Travelling Salesman Problem"" "3134": "Blackboard: Sorting" "3219": "handmade_render_group.cpp: Note that the current SortEntries function is O(n^2)" "3242": "Blackboard: Why SortEntries is O(n^2)" "3317": "Blackboard: On how to make sorting not be O(n^2)" "3395": "Blackboard: Walk through our current (Bubble sort) algorithm" "3493": "Blackboard: Walk through a "divide and conquer" (Merge sort) algorithm" "3870": "Blackboard: Compare these two algorithms" "4028": "Blackboard: Divide and conquer algorithms are O(n log n)" "4115": "Blackboard: Solidify the concept of the merge sort algorithm and "dynamic programming"" "4468": "Q&A" "4496": "NP stands for Nondeterministic Polynomial. Plus some other minor problems. Otherwise, well done" "4599": "For the record the remark I made earlier about Rust was not serious. Also, isn't mergesort n*log(n)?" "4628": "So unit testing a function that computes a path for the traveling salesman problem would require writing the algorithm twice, the second one testing the first?" "4684": "Do you think a computer science major is a good path to go? I'm in it now" "4745": "You say "exponential"" "4748": "To say that a problem is not solvable in polynomial time, you just say "The problem is not in P"" "4872": "Has anyone definitively proven that Travelling Salesman could not be in P, or is that still potentially NP-hard?" "4964": "TSP is NP-complete, so it is also in NP, so it DOES have a polynomial verifier" "4992": "Have they proven that it doesn't have a P verifier?" "5133": "Well it depends which TSP problem we are actually talking about" "5204": "Wouldn't saying that something is "NINPY" imply that P != NP? (Did we win a $1M prize?)" "5225": "Blackboard: "in P" / "not in P" vs "NP-complete"" "5442": "Idea: The game should include a traveling salesman, who ponders these things..." "5454": "Will we go into more complex sort algorithms like radix sort? Also, is the space requirement of mergesort something that needs to be take into consideration for Handmade Hero?" "5505": "Since you didn't go to college, when did you first get interested in or at least start learning all about big O?" "5605": "I'm not sure we can prove something is not in P unless it is undecidable or we can prove P != NP" "5634": "By the way, 8^2 doesn't equal 16" "5851": "I shall dig through my copy of Computers and Intractability by Gary and Johnson tonight" "5861": "Hmm, first sentence contains the word whimsical so it's looking good so far" "5889": "Wrap up with a recap" --- name: "day232" title: "Examples of Sorting Algorithms" markers: "8": "Share a link from yesterday's chat" "114": "Blackboard: Problem "difficulty" scale" "779": "Blackboard: Travelling Salesman Problem" "1357": "Thank Longboolean for the link" "1457": "Blackboard: Sorting" "1493": "handmade_render_group.cpp: Note that the current SortEntries function is O(n^2)" "1517": "Blackboard: Reiterate why we don't care about adding the n in Order Notation" "1616": "Blackboard: Scaling only matters if you actually scale!" "1795": "Debugger: Break into SortEntries and inspect the Count" "1839": "Blackboard: The relevance of scale" "1977": "Blackboard: "Worse case"" "2094": "Blackboard: Why the default sort in the CRT is quicksort" "2236": "Blackboard: More sorts" "2393": "Blackboard: The expected running times for these sorts in the worst case" "2471": "Blackboard: Quick sort" "2928": "Blackboard: Picking your pivots" "3045": "Blackboard: Using randomness to potentially improve the running time of algorithms" "3141": "Blackboard: Radix sort" "3463": "Blackboard: (Pseudo) Insertion sort" "3634": "Q&A" "3688": "So why would you not always do radix sort with a sort(sizeof(), data_)?" "3706": "Blackboard: On using the most appropriate sorting algorithm for the dataset" "4332": "Any news on potential Pat Wyatt guest stream to go more in-depth with the network stuff?" "4337": "Did you mention sort stability at all?" "4350": "Blackboard: Sort stability" "4654": "What else, if anything, do you think we'll need to sort besides the sprites?" "4671": "Could we possibly generate / hint the ground chunks in such a way that using radix sort would be more optimal?" "4692": "Yes, it is proven, I'm pretty sure" "4736": "Is shell sort basically bubble sort with a variable span between values being compared (span decreases each run through)?" "4746": "Blackboard: "Shell sort"" "4858": "Is this cross-platform yet?" "4906": "Would something like a pivot table be a sort problem, or something else altogether? Is that more a sort / amalgamation / summarization?" "4924": "Off-topic: Which more do you like, the fixed-function API of OpenGL or the programmable one? I've been using the modern approach but reading examples from the fixed pipeline they seem to be a lot more intuitive and easier to understand the flow of things" "4957": "So by your description, is a stable sort resource intensive? Since it seems like it could be of max O(n^2*nlogn) depending on sort type? Since you have to run through the data twice?" "5051": "When will you stop teasing us with the interactive fiction posts and get to the details?" "5060": "Will you leave in some bugs for speedrunners to break the game with?" "5089": "With a sort, is this actually adjusting and rewriting the data on the disk, or would it just be updating indexes or pointers? Just, once you sort, could you read start to finish, or is it pointer intensive: read 10 records, jump, read next 5, jump, read 2 more?" "5144": "I mean, how you actually went about solving the problems, it seems so close for weeks, then... cliffhanger" "5221": "I read a post the other day that said syntax coloring is bad for programming practices and enforces skimming rather then understanding. Do you agree or not?" "5279": "Now I know that I have to buy a game to find out, that's fine. Thank you" "5354": "Wind down" --- name: "day233" title: "Can We Merge Sort In Place?" markers: "72": "handmade_render_group.cpp: Note that the current SortEntries function is O(n^2), and introduce an early-out condition" "188": "Introducing this condition changes the "expected running time" from O(n^2) to something less" "237": "handmade_render_group.cpp: Introduce MergeSort" "538": "Blackboard: Can we Merge Sort in place?" "862": "handmade_render_group.cpp: Introduce a validator for the sorting functions" "930": "Debugger: Run the game and hit that assertion, before correcting the test" "978": "handmade_render_group.cpp: Continue working on MergeSort, interleaving the tests" "1405": "Blackboard: Draw out the scenario" "1444": "handmade_render_group.cpp: Introduce Half0StackCount and write out all the cases explicitly" "1606": "Blackboard: Walk through the problem" "1696": "handmade_render_group.cpp: Introduce Swap" "1808": "handmade_render_group.cpp: Step 1 - Find the first out-of-order pair" "1899": "Blackboard: The two phases of this merge sort algorithm" "1916": "handmade_render_group.cpp: Label the steps" "2054": "Blackboard: Walk through the next phase" "2154": "handmade_render_group.cpp: Step 2 - Swap as many items as necessary" "2426": "Blackboard: Draw out the current situation" "2633": "handmade_render_group.cpp: Step 3 - Swap back as many swapped half0 items as necessary" "3097": "Blackboard: Rearranging the entries" "3320": "Blackboard: Consider how to swap the order of these blocks" "3562": "Blackboard: Consider the two cases" "3705": "Blackboard: Walk through what happens" "3966": "handmade_render_group.cpp: Just set ReadHalf1 = InHalf1" "4008": "Blackboard: Construct a case and see what happens" "4243": "Blackboard: On the apparent need to store those back pointers" "4395": "handmade_render_group.cpp: Make MergeSort take some temporary storage and rewrite SortEntries to use that storage" "4769": "Debugger: Hit an assertion before fixing the test and seeing that the sort is correct" "5029": "Q&A" "5049": "I didn't look this up so it might not work, but came up with: whenever an element from the upper half is chosen, put it in place in the lower half, shift the upper half down to fill the space that the chosen element used to take up, and store the non-chosen element from the lower half in the new space at the end of the upper half, setting the lower half's read pointer to that end bit. Thoughts?" "5108": "Off-topic, but I made a post about the 2^(2^n)) arguments for TSP on the forums, if you're interested" "5119": "Could you post the bit of rotation math in the pre-stream in the Youtube Channel?" "5138": "One of the variants in the Wikipedia article claims only one slot + O(1) extra pointers, required." "5282": "Wrap it up" --- name: "day234" title: "Implementing Radix Sort" markers: "47": "Recap and set the stage for the day" "82": "handmade_render_group.cpp: Pull out the BubbleSort functionality into its own function" "160": "Struggle with the headphone cable" "229": ""I'm still being oppressed by The Cable Man"" "235": "Blackboard: Radix sort" "282": "Blackboard: "Stable sort"" "594": "Blackboard: "Some number of successive stable sorts on some part of the sort key"" "1324": "Blackboard: 8-bits" "1364": "Blackboard: How radix sort works" "1654": "handmade_render_group.cpp: Introduce RadixSort" "2362": "handmade_render_group.cpp: Introduce SortKeyToU32" "2383": "Run the game and hit an assertion" "2404": "Debugger: Step through RadixSort and inspect Dest, First and Temp" "2457": "Blackboard: 32-bit IEEE float" "2737": "Debugger: Step into SortEntries and inspect Entries" "2945": "handmade_render_group.cpp: Cast to SortKey to u32" "2965": "Debugger: Inspect the casted Entries" "3090": "handmade_render_group.cpp: Consider inverting the meaning of the bits" "3135": "Blackboard: On flipping the bits" "3183": "handmade_render_group.cpp: Set Result = Result in SortKeyToU32" "3225": "Debugger: Step into SortKeyToU32 and inspect Result" "3339": "handmade_render_group.cpp: Feed some basic values to SortEntries and inspect them" "3641": "Baby Owl of Shame Moment: We need to iterate on the ByteIndex in eights" "3693": "Run the game and see that it works now" "3746": "Q&A" "3774": "Why didn't you build merge sort from the bottom up? It makes ping-ponging the buffers much easier" "3836": "Your radix sort looks like it's O(8n) because you're doing two passes over the list per byte. Couldn't you make it O(5n) by getting all the offsets / counts in one pass at the cost of 3 more 256 element arrays?" "3979": "Off-topic: I'm a bit confused about axis-angle rotations vs quaternion rotations. I thought quaternions do represent an angle and axis of rotation. What's the difference?" "4025": "Blackboard: "Euler angles"" "4109": "Blackboard: "axis / angle"" "4152": "Blackboard: "quaternion"" "4217": "Blackboard: "exp map"" "4313": "I noticed the frame times are growing quite large now. Are you planning to optimize the software renderer further or switch to a hardware accelerated scheme?" "4345": "win32_handmade.cpp: Switch down to 960x540, disable the debug system and run the game" "4453": "Shut down the stream" --- name: "day235" title: "Initializing OpenGL on Windows" markers: "53": "handmade.h: Consult the TODO list" "242": "win32_handmade.cpp: Promote hardware acceleration to the top of the TODO list and embark on it" "355": "Run the game and note the weird fade thing" "418": "Set the stage for OpenGl" "513": "build.bat: Link to opengl32.lib" "580": "win32_handmade.cpp: #include opengl32.h>" "786": "win32_handmade.cpp: Introduce Win32InitOpenGL" "930": "Blackboard: OpenGL on Windows" "1402": "Blackboard: "DC" -> Device Context" "1729": "win32_handmade.cpp Write Win32InitOpenGL" "1915": "win32_handmade.cpp: Disable Win32DisplayBufferInWindow" "1959": "win32_handmade.cpp: Insert some OpenGL in this function" "2248": "Run the game and note that "we have no such pink screen to speak of"" "2269": "win32_handmade.cpp: Call Win32InitOpenGL, run the game and hit an InValidCodePath" "2308": "Internet: PIXELFORMATDESCRIPTOR" "2648": "win32_handmade.cpp: Initialise this struct" "3379": "Q&A" "3389": "Funny the pink didn't show up on the stream. OBS problem?" "3395": "We all just saw a black screen, not a pink screen..." "3423": "According to this you should use 32 for the ColorBit" "3478": "Curious if the CPU or the GPU actually communicates the information to the screen. I feel you mentioned this, but I forgot" "3541": "What are your thoughts about Vulkan?" "3554": "If you're ever in the mood to do a straight-up unrelated tutorial stream, IO completion ports would be great cause I ain't reading about that ***" "3580": "What do you think of Nvidia GE Force does not clear memory?" "3594": "Came in late. Do we have our own GL function pointers loaded now?" "3639": "Try a color other than pink? OBS might treat that as transparent" "3669": "Do you know why they deprecate GL_ALPHA?" "3687": "You don't need the DescribePixelFormat call, since when you use ChoosePixelFormat it modifies your DesiredPixelFormat with the correct stuff" "3737": "Since we will have a depth buffer, does the Z-sort really matter anymore?" "3792": "My bad! Looks like OpenGL docs are lying to me again" "3802": "Going to be doing multiple GL versions, or just the minimum for general Win XP machines? (What version are most of them even on anyway?)" "3848": "Would there be any benifit of using the new versions of OpenGL for a game like Handmade Hero?" "3870": "Is there a difference when calling a function (like glClear()) on the opengl32.lib vs the one on the graphics driver dll?" "3886": "Blackboard: Code library vs Import library" "3996": "Since we are using OpenGL, will you be modifying our 2.5D'ness or keep the code as is?" "4009": "For ChoosePixelFormat() were we not supposed to specify iPixelType and set it to PFD_TYPE_RGBA?" "4047": "win32_handmade.cpp: Set DesiredPixelFormat.iPixelType" "4094": "So by linking against opengl32.lib we don't need to use GetProcAddress at all with OpenGL?" "4136": "Blackboard: Dynamic link table" "4496": "Since you are complaining about windows pretty often, why don't you use another operating system?" "4548": "Do you think for the OS X port will you need a wrapper written in Objective-C to get use OpenGL and make a window?" "4580": "This is probably dumb, but what about offloading much of the computing we are doing onto the GPU using OpenCL, then not use OpenGL and keep things mostly as is?" "4657": "Over the break I wrote a program that generates OpenGL function pointer declarations and initialization by scanning cpp/h files to determine what needs to be added. Do you plan on doing something similar for Handmade Hero or will you keep it simple?" "4674": "How bad is an if statement in a shader?" "4693": "Have you ever programmed for a console?" "4722": "Linux has windows vista beat" "4790": "Wind it down" --- name: "day236" title: "GPU Conceptual Overview" markers: "7": "Recap and glimpse into the future of streaming via a video capture card" "126": "Run the game and note that Casey can see the game and we can't" "180": "Recap where we're at" "271": "Blackboard: GPUs" "420": "Blackboard: How the CPU relates to the GPU" "659": "Blackboard: A typical mobile setup" "799": "Blackboard: The implications of the system RAM and graphics RAM being separated by a PCI bus, i.e. latency" "939": "Blackboard: CPU vs GPU, historically" "1362": "Blackboard: A high level overview of GPU architecture" "1743": "Blackboard: How a GPU core works" "1898": "Blackboard: "Shader" != "CPU code"" "1985": "Blackboard: How if statments are executed on a GPU" "2206": "Blackboard: How loops are worked through on a GPU" "2271": "Blackboard: "Warp"" "2308": "Blackboard: Summarise what a GPU is" "2476": "Blackboard: How we program for the GPU" "2774": "Blackboard: "Pushbuffer"" "3206": "Blackboard: Plan for tomorrow" "3398": "Q&A" "3424": "You can instead of two triangles use a single triangle twice as big. It avoids the overdraw at the diagonal" "3513": "Quick CPU question: All it does on barebones physics level is run electrons through if-statements, right? (Go left, go right, etc., with transistors)" "3574": "Can't you run a Xeon Phi as your main processor, or did they make them dedicated only? Not like price / performance makes sense there" "3615": "What barriers are there currently from just using the CPU as a GPU?" "3709": "Can we make a "first person" 3D mode of the game, just for education?" "3715": "Where does the PS4 / XBone processor lie on the CPU / GPU spectrum?" "3858": "Intel has killed off many projects that made good money but had bad margins" "3956": "I've been told that lots of graphics drivers optimize for specific games (at the driver level). How does this fit into the equation? How do those optimizations make some games run better?" "4085": "Why does everyone good that works at Intel hate Intel, yet simultaneously Intel's engineering is so far ahead of everyone else's? It doesn't compute!" "4116": "What did you think about Larrabee?" "4136": "Does Vulkan fix the problem with OpenGL of not being able to transfer buffer-objects between processes with separate address spaces?" "4176": "Intel's compiler is meant to be really good, right?" "4211": "Can you give us some insight (without breaking any NDAs) how different from OpenGL console graphics APIs are?" "4346": "Sharing objects between applications without CPU overhead" "4363": "Why do you think there's no games about programming / hardware / history of PC / hardware? The domain is unimaginably rich" "4402": "How does GDDR RAM for GPU or concept of "memory chip designed specifically for GPU" enter into this picture?" "4428": "Blackboard: The gist of GDDR" "4596": "Could you one day maybe do a pre / after-stream short summary about your thoughts on OS-design and what you would do differently given current hardware?" "4617": "I mustered up one more. How come The Witness has 4GB RAM as minimum requirement? I don't doubt it has great optimization (as Jon is an apex-level programmer). Is it because nowadays everyone has 4 gigs at least and they thought it's unfeasible or too limiting to go below that? What can be the design behind that requirement?" "4787": "Why does it always seem like PC games claim that they require much more hardware power than they need? Do they want the extra power - just in case something goes wrong - or what?" "4859": "Having OS-level support for GPU resources for compute and graphics so that 3D graphics tools etc. can interoperate efficiently, e.g. in VFX production where you have lots of tools using the same data" "4905": "What would be a disadvantage of having a big beefy cpu (if any) or are there none?" "4920": "Have you seen that guy that is going to recreate Quake in a Handmade Hero style?" "4941": "How long do you expect this project to take?" "4968": "From what I get, Fallout 4 just allocates itself an 8 gig block. Abhorrent" "4997": "Quick question about strict aliasing due to your forum post (not defending it), but how would you propose compilers to understand that pointers do not overlap (to optimize loads and so on)? Not sure how we could improve generated code without having that kind of guarantee, assuming we need to still support old code" "5127": "Out of curiosity, back then when it came out, was GDI just a wrapper for OpenGL?" "5189": "Restrict doesn't seem to work with vs2013 / 2015" "5208": "Isn't Restrict, like, stupid limited though? And you don't have Alias (one that's definitive at least)" "5238": "Why is it that games get more difficult to play as Windows OS gets more advanced, i.e. playing a game from Windows XP on Windows 7?" "5280": "Wind down" --- name: "day237" title: "Displaying an Image with OpenGL" markers: "73": "win32_handmade.cpp: Disable PFD_DOUBLEBUFFER" "124": "Give it a shot and see our pink window" "153": "Recap our current situation" "307": "Blackboard: Ways of drawing quads" "407": "Blackboard: Using two triangles to draw our quadrilateral textures" "472": "win32_handmade.cpp: Explain glVertex nomenclature" "668": "Blackboard: Covering the screen with triangles" "723": "win32_handmade.cpp: Construct our first OpenGL primitive, a triangle" "780": "Run the game and "see" our triangle" "843": "Blackboard: Fixed function vs programmable pipelines" "1009": "Blackboard: Matrix multiplication" "1206": "Blackboard: Homogeneous coordinates and affine transforms" "1475": "Blackboard: Model View and Projection matrices" "1612": "win32_handmade.cpp: Use glLoadIdentity to set the MODELVIEW and PROJECTION matrices to the identity matrix" "1739": "Run the game and see the same thing we started with" "1744": "Blackboard: How OpenGL does Clipping" "2104": "win32_handmade.cpp: Pass glVertex2i the unit cube and then 0.9f" "2171": "Run the game and see the smaller rectangle" "2207": "Blackboard: Moving from Clip space to Screen space" "2387": "Blackboard: Drawing a texture" "2434": "win32_handmade.cpp: Do glColor3f before the two trianges" "2520": "Blackboard: Establishing our u,v texture coordinates" "2545": "win32_handmade.cpp: Set our texture coordinates" "2657": "win32_handmade.cpp: Use glTexImage2D to submit a texture to the graphics card" "3458": "win32_handmade.cpp: Use glTexEnvi and glTexParameteri" "3616": "Note that we aren't yet specifying the stride" "3674": "win32_handmade.cpp: Explain these parameters" "3874": "Run the game and see that we actually are there yet" "3889": ""It's all a lie"" "3977": "Q&A" "4016": "You used static instead of local_persist for Init" "4024": "win32_handmade.cpp: Introduce global_variable GLuint BlitTextureHandle" "4112": "Can we verify the vsync somehow?" "4140": "Are there any stretching issues when going from u,v coordinates to screen coordinates? If so, how would you fix it?" "4193": "The texture name you are binding is always zero after the first iteration" "4218": "I think in old OpenGL you don't even need glGenTextures, you can just pick your own arbitrary ints" "4231": "win32_handmade.cpp: Set GlobalBlitTextureHandle = 1; rather than using glGenTextures" "4371": "Would Texture Filtering (->GL_NEAREST) even occur when image and texture size is the same as it is now?" "4419": "In your professional career what GPU library have you preferred, such as OpenGL, DirectX, GLSL, etc.? Which one do you currently use and why?" "4443": "Later on, after we upgrade to more modern OpenGL, will the game render into a framebuffer and then onto the same triangles, or will you just have it render directly to the main window buffer?" "4525": "Before you removed the Init variable and inline initialization of the texture you were always passing 0 as the name, by the way" "4556": "So there is no way to blit directly to the back buffer anymore?" "4649": "Is there a difference in speed now we use OpenGL to move the buffer to the GPU?" "4781": "Is there a way you know of to optimize PCI transfers between CPU and GPU using OpenGL?" "4959": "I dunno if this is applicable to the last question, I literally just got here, but glTexSubImage2D could be faster than glTexImage2D" "4983": "Blackboard: glTexImage2D vs glTexSubImage2D" "5366": "At what point in that chain of gl commands does the card actually get involved? Command dependent? Driver dependent?" "5402": "Wrap it up" --- name: "day238" title: "Making OpenGL Use Our Screen Coordinates" markers: "9": "Recap and set the stage for the day" "134": "Recall how our graphics architecture works at the moment" "404": "Run the game and refresh our memory about where we left off" "545": "handmade_render_group.cpp: Look at how the renderer currently works and talk about the notion of separating out the renderer" "808": "Create handmade_opengl.cpp and translate RenderGroupToOutput into it" "1198": "handmade_opengl.cpp: Introduce OpenGLRectangle" "1547": "Blackboard: Maths" "1581": "Blackboard: Projecting the P from clip space to screen space" "1947": ""Life is hard"" "1966": "Blackboard: Setting up our transformation matrix" "2469": "win32_handmade.cpp: Write our new OpenGLRectangle function inline, passing it the old values at first" "2594": "Run the game and see our old bug" "2649": "Internet: glLoadMatrix" "2729": "win32_handmade.cpp: Initialize Proj array to pass to glLoadMatrix" "2845": "win32_handmade.cpp: #include handmade_intrinsics.h and handmade_math.h" "2874": "Run the game and see that everything does not just work" "2893": "Blackboard: Mathematical vs Computational matrix multiplication" "3206": "win32_handmade.cpp: Re-encode the Proj array for OpenGL's benefit" "3377": "Q&A" "3424": "I'm gonna start? Yeah i installed a driver software company. Kapp?" "3436": "What keyboard layout do you use?" "3447": "Will handmade_opengl.cpp be included in the platform layer or game layer?" "3549": "Jumped in a bit late, so are we using the fixed-function OpenGL API right now, or will we write our own matrix struct at some point?" "3592": "Wrist braces - recommended for programmers in general, or just something you've had issues with?" "3607": "If you include handmade_opengl.cpp in the game layer, won't that force you to include windows.h and all the OpenGL headers in the game layer?" "3701": "Was push buffer rendering primarily in the software renderer because the real hardware renderer works that way due to GPUs?" "3736": "Will the game be given away to dev viewers for free?" "3761": "Off-topic: Have you worked with, talked to or met Andre Lamothe before?" "3786": "I feel uncomfortable with floating points representing pixels. Have you ever had problems with OpenGL and floating point values, like passing them to shaders, or texture coordinates?" "3925": "Do you use any EBO (element buffer object) or VBO (vertex buffer object) in your OpenGL code? If no, why?" "4115": "Did you do your own glOrtho call when you set up the projection matrix? Also, thanks for all the matrix explanations" "4316": "Stream has ended" --- name: "day239" title: "Rendering the Game Through OpenGL" markers: "8": "Recap and set the stage for the day" "86": "handmade_opengl.cpp: Look at the new hardware rendering code and consider how to enable the renderer to work through software as well as hardware" "341": "handmade_render_group.cpp: Introduce RenderToOutput to pick whether to render with OpenGLRenderGroupToOutput or TiledRenderGroupToOutput" "617": "handmade_platform.h: typedef platform_opengl_render and add *RenderToOpenGL to platform_api" "689": "Leave it as a little bit of a zygote" "704": "handmade_opengl.cpp: Make RenderGroupToOutput only take *RenderGroup" "761": "Run the game and wonder how THAT just happened" "789": "Debugger: Step into GameUpdate and realise that we're using the old function" "849": "Run the game again and hit a first-chance exception" "856": "win32_handmade.cpp: #include "handmade_opengl.cpp"" "914": "handmade_opengl.cpp: Make OpenGLRenderGroupToOutput take *OutputTarget" "1070": "Run the game and see just our debug info" "1116": "win32_handmade.cpp: #if0 the buffer drawing code" "1153": "Run the game and see a bunch of solid nonsense" "1173": "handmade_opengl.cpp: Send a texture to OpenGL every frame" "1272": "Run the game and see that it almost works" "1380": "Blackboard: Blending" "1898": "handmade_opengl.cpp: Enable GL_BLEND and use glBlendFunc to specify the blending equation" "2003": ""It's almost like the hardware is set up to do this!"" "2009": "Run the game and see that we are successfully reproducing our image" "2041": "handmade_render_group.h: Add Handle to loaded_bitmap to store whether the bitmap has been submitted" "2159": "handmade_opengl.cpp: Conditionally bind the texture or set the handle" "2266": "Run the game and see that it now runs much zippier" "2298": "Debugger: Learn that we have a bug in the validation code" "2349": "Run the game and point out that the image has a shimmering look to it" "2404": "handmade_opengl.cpp: Re-enable bilinear filtering with glTexParameteri" "2516": "Run the game again and note that we look a lot more like the software renderer, but that our ground chunks are now messed up" "2807": "Describe the problems with the current architecture, enabling the debug system in the process" "3056": "Blackboard: The previous and new flows of data" "3321": "Q&A" "3372": "Why did you choose OpenGL over DirectX?" "3634": "Did you notice that the ground tiles changed when you introduced sorting?" "3678": "I've asked this before, but I want to hear your case again, what specific things make a data-protocol based interface better than one with function calls?" "3948": "How is V-Sync controlled?" "3981": "Does the GPU do sRGB correction automatically?" "4060": "I wasn't paying close attention, but has the OpenGL texture name thing broken hot-reloading?" "4091": "What languages do you know" "4097": "Are there any performance reasons to choose compatible OpenGL API vs Core, or is it just the fact that we get to use programmable shaders in Core?" "4215": "Is there any good reason for desktop GPUs to not have programmable blend modes? Because I've seen that most mobile GPUs have that" "4251": "Blackboard: Tiled (mobile) vs Non-tiled (desktop) Framebuffer" "4646": "Do we get gamma correct rendering "for free" now?" "4676": "Doesn't the OS automatically V-Sync you, or does that only apply in windowed mode?" "4693": "So gamma curve is also a OpenGL extension?" "4700": "I know you're probobly sick of all the Vulkan questions, but here is another one. A lot of places online frame Vulkan as the next version of OpenGL, their thought being that once Vulkan is released development / adoption of OpenGL will dwindle to the point where OpenGL drivers are no longer developed by graphics card manufacturers. Could this happen? And in the event that it does, what is your plan?" "4826": "You stated that the APIs are very similar, but is there a visual effect that can be accomplished on DirectX and not on OpenGL or vice versa?" "4860": "Is there a good reason why windows OpenGL headers only offer the old legacy stuff while other platforms add new stuff?" "4913": "At some point can you go over the pros and cons of the different graphics APIs?" "5101": "Call it a day" --- name: "day240" title: "Moving the Renderer into a Third Tier" markers: "29": "Recap and set the stage for the day" "149": "handmade_platform.h: Replace game_offscreen_buffer with game_render_commands" "756": "handmade_platform.h: Introduce InitializeRenderCommands" "800": "handmade_platform.h: Point out that the #inline part of game_render_commands won't work, before turning it into a #define" "1064": "win32_handmade.cpp: Pass RenderCommands to everything that needs it" "1279": "Note that this is where the three-tiered architecture emerges" "1354": "win32_handmade.cpp: Conditionally display the software renderer via hardware or a StretchBlt" "1497": "handmade_opengl.cpp: Introduce DisplayBitmapViaOpenGL" "2375": "Blackboard: The three-tiered architecture" "2440": ""I didn't fall asleep yet, so that's good"" "2447": "handmade_render_group.cpp Work through the compile errors" "3499": ""These ground chunks have been nothing but annoying the entire time..."" "3654": "handmade.cpp: Continue cleaning up the compile errors" "4346": "Q&A" "4390": "So no more hot code reloading for renderer code?" "4442": "Did you see the Handmade Quake? Can you confirm whether it's of Handmade quality?" "4458": "Casey, you seem to have a grudge for the ground chunks. Do you really hate them that much?" "4547": "Less of a question but more of a thanks for doing this. You've inspired me to pick up C and C++ again after quite a long break, so thanks" "4556": "What was your original goal with the ground chunks and how has that changed? Also if you remove them what will you replace them with?" "4637": "You may want to include a note in today's zip file about how it won't compile" "4643": "build.bat: Leave a note from The Management" "4695": "Why are you wearing earbuds? Are you listening to something?" "4708": "Would you at some point compile a list of "stuff programmers should know"? I'd like some beginner level pointers like "these are algorithms / algorithm types you should know", sorting being one type and such" "4791": "Wrap it up" --- name: "day241" title: "OpenGL VSync and sRGB Extensions" markers: "8": "Reminder: The source code is not in the public domain yet" "57": "On the possibility of vomiting" "99": "Recap and set the stage for the day" "173": "win32_handmade.cpp: Make Win32DisplayBufferInWindow take SortMemory" "304": "handmade_render.cpp: Make SortEntries take that SortMemory and continue cleaning up compile errors" "433": "handmade_render.cpp: Rename RenderGroupToOutput to TiledCommandsRender and make it take game_render_commands *Commands" "519": "handmade_render.cpp: Pull tile_render_work in from handmade_render_group.h" "549": "handmade_render.cpp: Rename RenderGroupToOutput to RenderCommandsToBitmap" "594": "handmade_render.cpp: Consider using the AddEntry call directly" "676": "win32.handmade.cpp: Make platform_api available to the renderer" "731": "win32_handmade.cpp: Continue cleaning up compile errors" "1289": "handmade_platform.h: typedef u64 umm" "1368": "handmade_render.cpp: Move DrawRectangleQuickly in from handmade_optimized.cpp" "1423": "build.bat: Remove the handmade_optimized.cpp build" "1503": "Build and run and crash in PushRenderElement" "1552": "win32_handmade.cpp: Correctly allocate memory for the PushBuffer" "1589": "Build and run successfully the first time!" "1645": ""Everything just worked"" "1688": "win32_handmade.cpp: Introduce GlobalUseSoftwareRendering to enable us to switch between software and hardware rendering" "1782": "Run the game and toggle between the renderers" "2008": "Blackboard: VSync" "2207": "Blackboard: glSwapInterval" "2338": "Internet: docs.GL [see Resources]" "2372": "Internet: WGL_EXT_swap_control [see Resources]" "2447": "handmade_opengl.cpp: Try calling wglSwapInterval(0)" "2480": "win32_handmade.cpp: Call wglGetProcAddress to get wglSwapIntervalEXT" "2600": "win32_handmade.cpp: typedef BOOL WINAPI wgl_swap_interval_ext" "2692": "Run the game and see that we're now running at a locked 60 FPS" "2752": "win32_handmade.cpp: Note that we are not done yet" "2917": "Run the game and note that our hardware renderer doesn't understand the fact that we're using sRGB" "3006": "Internet: ARB_framebuffer_sRGB [see Resources]" "3189": "handmade_render.cpp: Look at how our software renderer does gamma correction" "3405": "win32_handmade.cpp: Conditionally use SRGB8_ALPHA8_EXT if the necessary extension is present" "3514": "win32_handmade.cpp: Turn on GL_FRAMEBUFFER_SRGB" "3595": "win32_handmade.cpp: #define the GL_ extensions we want" "3700": "Blackboard: ARB - "Architecture Review Board"" "3766": "win32_handmade.cpp: Comment out the checks to see if the extensions are available" "3814": "Run the game and find that we have actual sRGB rendering happening" "3875": "Q&A" "3935": "Will you be implementing multiple render paths depending on the OpenGL context version or available extensions at runtime?" "3968": "Can you fix the Santa sorting?" "3980": "handmade_cutscene.cpp: Fix the Santa sorting" "4186": "Your maximum frame time is about 2-3ms without VSync enabled, but with it enabled I see it stays at 16ms most of the time, but sometimes goes to 17ms. Does that mean it will skip a frame? Is that a problem with VSync?" "4216": "Blackboard: SwapBuffers" "4508": "Is object oriented programming bad in general or for game purposes, and why?" "4515": "I believe you do an strstr of GL_EXTENSIONS, then check if the end of the extension is null, a space or tab to see if it exists" "4534": "Is there any reason to make the swap interval larger than 1?" "4554": "Blackboard: Swap interval" "4593": "Is there an asynchronous way to do VSync? I mean, a way to "ask" OpenGL if it has displayed the frame or how much time you have to wait until the frame is going to be displayed" "4640": "How would you allow the game to run at a non-60 FPS rate and not speed up / slow down the animation speed?" "4675": "Apologies if you explained this before. Since rotation is stored in the upper 3x3 part of the transform matrix, and Scale is stored in the 0,0, 1,1, 2,2 diagonal, how do the play well together? I mean, wouldn't changing the rotation or scale affect the other?" "4698": "You mentioned 120hz. How do you handle skipping every other VSync event? Do you just detect the monitor refresh rate and if 120hz swap twice in a row?" "4721": "If VSync is disabled in windows, will there be no VSync at all?" "4739": "The glove in the scene where Krampus is giving it to the kid looks a bit strange with the thumb pointing downwards" "4747": "Why does VSync cause input lag on some machines?" "4791": "What are the trade-offs of storing the textures on disk in the same linear colorspace format you are using?" "4837": "Any update on when to implement sound effects?" "4844": "What is that bottle full of that Jon posted on twitter?" "4854": "We're still fading from / to the desktop. Did you have to reimplement that? Is it being hardware rendered? Is the fade here to stay?" "4880": "With WglSwapInterval() do we still have to do Sleep at the end of the frame? Could you also comment on glFinish / glFlush and how they're used?" "5040": "Will you use EXT_swap_tear? (-1 in the SwapInterval call)" "5047": "Should we wait after SwapBuffers if it returns too fast?" "5067": "Would it be better to minimize or maximize how much you do per frame? Like, would it be better to make your program take any time that it would be waiting for VSync, and instead focus it on performing more computations, even potentially computing things ahead of time?" "5124": "How do you easily detect if VSync is active?" "5151": "How do I VSync and prevent tearing with a dual-monitor setup? Is it any different than a single-monitor setup? [see Resources]" "5243": "Conclude" --- name: "day242" title: "OpenGL Context Escalation" markers: "8": "Recap and set the stage for the day" "221": "Run the game and point out that we experience a pause while textures get loaded in" "439": "win32_handmade.cpp: Clean up and consult the TODO list" "456": "win32_handmade.cpp: On checking for OpenGL extension strings" "547": "handmade_opengl.cpp: Move the GL_ defines in from win32_handmade.cpp and introduce OpenGLGetInfo" "1051": "Run the game and inspect our opengl_info" "1143": "handmade_opengl.cpp: Parse the available extensions and compare them with our requirements" "1352": "handmade.h: Write a new version of StringsAreEqual" "1411": "handmade_opengl.cpp: Use StringsAreEqual to continue with the extension comparison" "1757": "Debugger: Inspect the Extensions string" "1994": "Debugger: Run through OpenGLGetInfo and see what the parser is doing" "2106": "handmade_opengl.cpp: Introduce OpenGLInit" "2226": "Context escalation" "2539": "Internet: WGL_ARB_create_context" "2693": "win32_handmade.cpp: typedef and use wglCreateContextAttribsARB to check which OpenGL context we're on" "3213": "Debugger: Step into wglCreateContextAttribsARB and see if it works" "3573": ""And now it's like Mr. Doesn't-Want-To-Do-That-For-Me"" "3604": "handmade_opengl.cpp: #define GL_SHADING_LANGUAGE_VERSION and use it in OpenGLGetInfo" "3687": "Debugger: Step into OpenGLGetInfo and inspect the ShadingLanguageVersion" "3724": "Q&A" "3766": "Looking at winXP and cards, looks like they need GL 2.0 as the 'max' they can support, more or less (if you use era cards)" "3803": "In the function OpenGLGetInfo why did you do an "#if 0 ... #else ... #endif" rather than just commenting it out?" "3832": "For sRGB do you also have to set WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB when you choose the pixel format or is that something different?" "4162": "From connor_rentz (just left): What is umm data type and what is it used for? I will watch the recording" "4187": "Yes, that's what I was talking about. I didn't notice you did more there" "4191": "What's the difference between sRGB and RGBA?" "4219": "Blackboard: sRGB" "4618": "I just checked my Dell monitor. It has Adobe RGB as well as sRGB modes and they look fairly different. So what's the better one?" "4714": "I've heard a lot of monitors aren't even really 32-bit color. Sometimes less with dithering in the monitor" "4758": "Shut down now" --- name: "day243" title: "Asynchronous Texture Downloads" markers: "3": "Welcome back" "78": "Promote 4coder and discuss modal editing" "642": "Recap and set the stage for the day" "768": "Blackboard: Texture Downloads" "914": "Blackboard: Thinking of the GPU memory like a cache" "1126": "Blackboard: Swizzling" "1164": ""CBAD, that's my rapper name"" "1571": "Blackboard: Power of 2 textures and modern rectangular texture processing" "1752": "Blackboard: The problems with our current texture downloading scheme" "2039": ""Drivers and Windows. They conspire to "help" you"" "2045": "Blackboard: Asset stores" "2238": "Blackboard: How the CPU asset store works" "2332": "Blackboard: The GPU asset store" "2520": "handmade.cpp: Return to the codebase" "2525": "handmade_opengl.cpp: How our loading currently happens" "2654": "handmade_asset.cpp: Refresh our memories as to what LoadBitmap and LoadAssetWorkDirectly do" "2950": "handmade_opengl.cpp: Move glTex* calls to handmade_asset.cpp and consider holding the frame if we are not ready with the texture" "3067": "win32_handmade.cpp: Pull the pieces of the picture together" "3242": "win32_handmade.cpp: Call Win32CreateOpenGLContextForWorkerThread in ThreadProc" "3344": "win32_handmade.cpp: Introduce Win32CreateOpenGLContextForWorkerThread" "3738": "win32_handmade.cpp: Introduce struct win32_thread_startup" "3871": "win32_handmade.cpp: Pass Startup to Win32MakeQueue directly" "3979": "win32_handmade.cpp: Undo and introduce GlobalOpenGLRC and GlobalDC instead" "4273": "Run the game and see nothing" "4322": "win32_handmade.cpp: Add bool32 NeedsOpenGL to platform_work_queue" "4562": "Run the game and still see nothing" "4599": "handmade_platform.h: Add platform_allocate_texture and platform_deallocate_texture to platform_api and add their equivalent calls" "4803": "handmade_asset.cpp: Call Platform.AllocateTexture in the FinalizeAsset_Bitmap case" "5190": "win32_handmade.cpp: Write PLATFORM_DEALLOCATE_TEXURE" "5281": ""The stream actually hasn't ended..."" "5648": "handmade_asset.h: Add AssetType to asset_memory_header" "5996": "Run the game, see nothing and leave it at that" "6081": "Q&A" "6090": "Are we missing a Day in the episode guide? The guide only goes up to Day 242, but today's overlay was saying Day 244" "6159": "Is it possible to tell OpenGL which graphics card to use if you have more than one in a given machine?" "6326": "Is it really a good idea to keep the DC around forever? What if the user changes their monitor config while Handmade Hero is running?" "6367": "Wouldn't the allocate and deallocate texture fit better in the opengl.cpp layer instead of the platform?" "6386": "handmade_opengl.cpp: Move PLATFORM_ALLOCATE_TEXTURE in from win32_handmade.cpp" "6413": "What is Microsoft's rationale for not allowing exclusive fullscreen mode for Universal Windows Platform games? Seems like that would just shoot themselves in the foot" "6499": "Is there a way to preload vertices / normals / colors to the card in the same way as textures (e.g. before glDrawElements is called) or is that usually never an issue?" "6590": "Could you invite Jeff to "supervise" and "micromanage" you while coding sometime?" "6654": "For 3D models isn't it typical to upload the mesh to the GPU once and write a shader that takes a transform matrix for drawing each model?" "6778": "It was just for entertainment reasons, I wasn't implying anything else. Jeff saying: "you know, I really don't like the name of that "variable""" "6841": "How the heck do you even read code with one letter variables?" "7015": "Thank you for the stream. We are not doing a good job asking relevant questions, obviously" "7079": "Wrap it up for now" "7114": "Promote 4coder" --- name: "day244" title: "Finishing Asynchronous Texture Downloads" markers: "55": "Build and run the game and note that our textures don't get downloaded" "92": "Set the stage for the day with some thoughts on writing software from scratch and the occasional need to use systems which are black boxes" "315": "Debugger: Take a stroll through our new OpenGL code" "548": "win32_handmade.cpp: Make Win32InitOpenGL return an HGLRC" "740": "Debugger: Step into Win32InitOpenGL and consider creating the OpenGL context outside of the queue" "826": "win32_handmade.cpp: Claim the Window as a CS_OWNDC" "865": "Debugger: Step into Win32CreateOpenGLContextForWorkerThread" "920": "Explain what is happening in the debugger while two threads are initialising OpenGL" "1154": "win32_handmade.cpp: Assert if wglMakeCurrent fails" "1192": "Run the game and note that we never hit that assertion" "1233": "Debugger: Step through Win32AllocateTexture" "1308": "handmade_asset.cpp: Set FinalizeOperation to FinalizeAsset_Bitmap" "1352": "win32_handmade.cpp: Put in the pointers to AllocateTexture and DeallocateTexture" "1385": "Debugger: Step through Win32AllocateTexture and see the game correctly rendering in hardware" "1566": ""I don't know how that ended up working"" "1598": "Mention the fact that there's no synchronisation between the texture downloading and the rendering, and describe our goal with regard to failure cases" "1996": "handmade_opengl.cpp: Explain the importance of gamma correction" "2173": "handmade_opengl.cpp: Explain why there are two separate enables for sRGB" "2300": "Internet: Consult the OpenGL docs" "2704": "win32_handmade.cpp: typedef these WINAPI wgl_ functions and enable the extensions in Win32InitOpenGL" "4128": "Q&A" "4150": "Don't you have a race condition according to the C11 and C++11 memory models when you set the texture handle from the worker thread and read it on the rendering thread without any synchronization? I think you need to use an atomic operation or the compiler could mess up the generated code" "4243": "Why don't you render directly to the backbuffer at Molly?" "4460": "FYI, no you can't change pixel format once it's been set. Need to create a temp window & context, get the wgl*arb function pointers, then destroy context & window and create new window and context with wgl*arb. Very annoying but that's how it works on windows as far as I know" "4509": "Will we be back to the debug code and finish it up after this, or have we finished it now?" "4523": "Thanks for the in depth explanation. Will you be going over modern GL later?" "4635": "Apparently in DirectX 12 you can select a separate context for different GPUs" "4690": "Where did you upload the 4coder videos?" "4713": "Yes, D3D11, too" "4738": "Couldn't you also use a PBO for streaming in textures?" "4835": "Wrap it up" --- name: "day245" title: "Using wglChoosePixelFormatARB" markers: "47": "Blackboard: PBO's (Pixel Buffer Objects)" "171": "Blackboard: Virtual Addresses, Physical Addresses and the TLB" "299": "Blackboard: The GPU does not have access to the TLB" "380": "Blackboard: How the GPU transfers the textures into its memory" "772": "Load the code and set the stage for the day" "896": "win32_handmade.cpp: Move wglGetProcAddress until after we have created a Context" "1045": "win32_handmade.cpp: Nullify the Context and try setting the PIXELFORMATDESCRIPTOR again" "1129": "Debugger: Step into wglMakeCurrent" "1285": "win32_handmade.cpp: Try destroying the Context a little later and then step through again to see if the pixel format got successfully changed" "1448": "win32_handmade.cpp: Introduce LoadWGLExtensions" "1508": "Crash 4coder and investigate what happened" "1719": ""Minidump with heap, bro"" "1747": "A few words on the helpfulness of submitting crash reports to developers" "1809": "win32_handmade.cpp: Introduce Win32LoadWGLExtensions" "1964": "win32_handmade.cpp: Introduce Win32ChoosePixelFormat" "2484": "win32_handmade.cpp: Call Win32LoadWGLExtensions in Win32InitOpenGL and test to see whether or not we are able to get a ModernContext" "2693": "Debugger: Step into Win32LoadWGLExtensions and follow what happens" "2785": "win32_handmade.cpp: Revert to the old way of creating two DCs" "2891": "Debugger: See if we have any better luck with that" "2936": "Moment of realisation: We forgot to call Win32SetPixelFormat on WindowDC" "2996": "Debugger: Step into Win32SetPixelFormat and find that it works" "3132": "win32_handmade.cpp: Use WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB" "3228": "Run the game..." "3287": "...and see stuff that we cannot see on stream" "3337": "win32_handmade.cpp: Set WGL_DOUBLE_BUFFER_ARB to GL_FALSE for the benefit of the stream" "3363": "Run the game for us all to see" "3446": "Q&A" "3460": "Aren't pretty much all games double buffered? If so, why doesn't OBS have problems capturing game footage for other games?" "3535": "Does this mean Handmade Hero cannot be let's played?" "3574": "There's a scene switcher plugin in OBS" "3615": "Shouldn't we also call GetPixelFormat to make sure we got what we wanted?" "3741": "So for games that is fine, but for something like photoshop I am assuming you would have to care?" "3877": "Have you started thinking about cross-platform support? I've missed quite a bit of the stream" "3948": "Is the GPU doing pre-multiplied alpha?" "4114": "Are you staying with immediate mode?" "4146": "Could we do sRGB with a shader and not with glEnable?" "4234": "Are we still going to do work on the debug UI?" "4267": "Every time you go to answer a question and the cutscene loops, a pink screen appears" "4328": "Wrap it up" --- name: "day246" title: "Moving Worker Context Creation to the Main Thread" markers: "45": "Recap and set the stage for the day" "277": "win32_handmade.h: Move platform_work_queue in from win32_handmade.cpp" "388": "win32_handmade.cpp: Initialise a Thread and Queue in ThreadProc and change to testing to see that we have an OpenGLRC" "516": "win32_handmade.cpp: Make Win32MakeQueue take a win32_thread_startup" "638": "win32_handmade.cpp: Initialise some High and Low priority threads and make the first two LowPriStartups to be populated by Win32GetThreadStarupForGL" "784": "win32_handmade.cpp: Replace Win32GetThreadStarupForGL with one that returns a win32_thread_startup" "896": "Debugger: Step through the win32_thread_startup initialisations" "987": "win32_handmade.cpp: Remove GlobalOpenGLRC and GlobalDC global variables and try stepping through again" "1033": "Run the game and see our textures" "1083": "Internet: Consult the WGL_ARB_pixel_format docs" "1294": "handmade_opengl.cpp: Consider how to get the wgl extensions" "1406": "Internet: Consult the WGL_EXT_extensions_string doc to confirm that in order to check that you have a wgl extension, you have to have a wgl extension" "1474": "win32_handmade.cpp: Use wglGetExtensionsStringEXT to see what extensions strings we have" "1753": "Internet: ARB_framebuffer_sRGB" "1848": "Beg to differ" "1881": "Debugger: Inspect our Extensions" "2121": "todo.txt: Consult the TODO list" "2274": "Run the game and test out our hot code reloading" "2500": "win32_handmade.cpp: Note that the Entry.Callback is not in the same place between builds and consider how to solve this problem" "2659": "todo.txt: Update the TODO file" "2813": "Q&A" "2821": ""So what shall we do for the next 20 min? Maintain the TODO file"" "2865": "There is a bug in the new GL code, the if(!) you added is not checking the sRGB variable but a different one" "3222": "Thank you to imperiumtactics for following the channel! <3" "3252": "Totally serious when I say you should write an API book. I would never think of lots of stuff" "3320": "For the keyboard / gamepad inputs, can HalfTransitionCount ever go beyond 1? Or is it there if you put the input getting on a separate thread?" "3460": "Kind of graphics / Windows related: Why do so many games, especially Source games handle Alt-Tab poorly?" "3631": "Is there any benefit to moving the main windows message queue to another thread? I'm sorry if you've implemented / answered this already. I'm still catching up" "3907": "Do you use Windows's GDI outside of the educational usage you have been showing?" "4046": "Promote 4coder!" "4051": "Sounds like you know how to play drums?" "4058": "What do you think of Vulkan? Will it replace D3D?" "4217": "Selection buffer vs ray picking vs color picking for mouse picking?" "4233": "For detecting long presses on keyboards, would I put a timestamp in the input struct?" "4255": "What is the next "feature" you are going to work on?" "4266": "Do you think all the modern C++ nomenclatures like C++11, C++14, C++17, C++xy are an internal joke to obscure the mess the language is?" "4368": "Is it worth selling my soul and learning JS / Python for money?" "4488": "Any thoughts on SDL2?" "4496": "What technique are you going to use for path-finding?" "4503": "Been doing a lot of JS. What do you think I should do next? Kind of bored with JS" "4536": "Vulkan is extremely low level; that was requested by various game engine and hardware developers. There is probably a huge market for a dev-friendly API to sit on top of Vulkan to shield devs from those gory details. Don't think so?" "4769": "ow much do you follow the latest technologies? Do you think it is a waste of time to learn the latest graphics API for indie development?" "5006": "Why should no programmer work for Palantir?" "5076": "Does Jon use more C++ specific stuff than yours do?" "5158": "What you think about the new Snowdrop game engine?" "5184": "Do you plan on using Vulkan considering the performance differences that people have been claiming exist?" "5257": "Since you write everything from scratch, why not use a language like Go?" "5284": "If any, what games have you been playing recently and how did you like them?" "5318": "I have noticed that there is no more send email on the Handmade Hero website. Do you still reply to emails?" "5364": "Where do you see the game development community going in the next 5-10 years?" "5369": "What are the main differences in, for example, C and the language your friend is developing, in three sentences or less?" "5378": "Do you have experience with POSIX Linux system calls, fork() for example? I need to create a small Process Scheduler, but when I create a fork() inside a for cycle it messes up. I need to create N amount of processes, then save them to a FIFO list and start executing one at the time" "5470": "Would you want to be one of the first people to play around with JAI? Or would you wait 'till it gets more mature?" "5557": "Are you going to check out OBS Studio this weekend?" "5563": "Do you work on another game project other than Handmade Hero?" "5601": "Is fork a good API or a bad API?" "5679": "Forgive me if already asked: GDC is next week. What Handmade Hero representation at GDC?" "5748": "Wind things down" --- name: "day247" title: "Simplifying Debug Values" markers: "9": "Welcome. Details about the texture transfer saga." "86": "nvidia didn't respond yet about _how_ to properly transfer textures overlapped." "114": "Overlapping CPU work and GPU work are not the same thing. There are 2 required copies that have to happen in order for the textures to get to the GPU: one off of the disk into memory that GPU can _see_, and then from the memory that the GPU can see into the actual memory resident on the GPU." "171": "Direct GPU Mapping process description" "253": "How do we tell the driver to start transferring textures using the asynchronous memory transfer capabilities that the card has" "325": "Decision to wait for nvidia's response about what they think the best way to transfer textures would be" "352": "Reminder that we don't fence the download on either side and doubt about whether that creates problems" "399": "Alternative approach - we could just continue to download textures on a single thread" "518": "Decide to fix the debug code" "569": "Reminder that on the AMD machine that Casey uses, the texture download problems don't seem to happen" "594": "glFlush() seems to force the download to happen on a separate thread" "635": "Reminder about the original debug code purposes" "703": "Focus on the debug interface" "836": "win32_handmade.cpp GlobalPause and GlobalUseSoftwareRendering would be nice to be included in the interface" "1025": "win32_handmade.cpp - DEBUG_EDIT() as a means to include GlobalPause and GlobalUseSoftwareRendering" "1157": "Doubts on the usage of handmade_config.h as a means to specify debug variables" "1314": "win32_handmade.cpp - replacing DEBUG_EDIT() with DEBUG_VALUE() and checking if it works" "1475": "Unhandled End Data Block" "1533": "Debug interface is not visible in in-game mode" "1660": "Check if debug components are drawn by not rendering the world" "1751": "Add a clear before drawing" "1774": "Confirmation that the debug interface doesn't show up in-game because of a sorting problem" "1867": "handmade_render_group.cpp - Add a SortBias to PushBitmap -> Dim.Basis.SortKey" "1947": "handmade_render_group.cpp - Investigate where and why is CAlign still used. [just for debug drawing]" "2128": "handmade_debug.cpp - add a FLT_MAX sort bias to the PushBitmap call so that we get the debug interface closest to us (on Z)" "2195": "handmade_debug.cpp - add a drop shadow to the text by duplicating the PushBitmap call, slightly displacing the position and changing the color" "2316": "Getting back to what we were doing - check if if interactive selection works and confirming that End Data Block UNHANDLED is not a bug introduced by the addition of GlobalPause and GlobalUseSoftwareRendering" "2374": "Checking the debug printout hierarchy" "2403": "win32_handmade.cpp - Checking how "Platform" should work in DEBUG_BEGIN_DATA_BLOCK()" "2411": "handmade_world_mode.cpp - Simulation_Entity | Confirm that printing block names is not yet implemented properly" "2501": "handmade_debug_interface.h - Minimize complexity by removing DEBUG_IF and DEBUG_VARIABLE" "2572": "Pulling out calls to DEBUG_VARIABLE and DEBUG_IF into globals ourselves" "2655": "handmade_config.h - Change #defines to global_variable" "2742": "handmade_render_group.cpp - Check we don't have code that writes to handmade_config.h" "2765": "Checking where handmade_config.h is included [in handmade_platform.h] and moving the inclusion to handmade.h" "2823": "Correcting types and initializers for globals in handmade_config.h and changing DEBUG_IF and DEBUG_VARIABLE calls in the rest of the code, removing compile errors one by one until..." "2985": "...reaching Global_Renderer_ShowLightingSamples, which is moved directly to handmade_render.cpp" "3078": "win32_handmade.cpp - Moving (and afterwards eliminating) Global_Renderer_UseSoftware from handmade_config.h and creating an enum with the rendering type, which allows to manage the Win32DisplayBufferInWindow cases better." "3433": "win32_handmade.cpp - The reason for ordering the enum components is for having the 0 value being the default" "3498": "Plans for next day: hooking up debug printout for editing and maybe cleanup" "3537": "Q&A" "3630": "Casey, at what point is it _bad_ to separate everything into multiple files, and when is it _good_?" "4056": "Okay, so basically personal preference, compile time, and external impositions. Thank you very much for your answer :)" "4066": "Does "texture download" on this stream mean "glTexImage2D"?" "4223": "Have you ever used #pragma section(...) and grouped memory into sections, and read the map file, or have you always used this style of meta programming?" "4251": "Off-topic: If you wanted to extend the hot-code reloading to work with structure changes wouldn't you have to store meta data about each struct along with information about every allocation, so that you could walk the data, adjust the data, move things around and fix pointers?" "4334": "Do you specifically have to say inline for functions to be inlined or does the compiler do that automagically if it finds one/several to fit?" "4507": "Would you try to fix the memory in-place or would you copy it to a new memory arena?" "4547": "Programming style - why do you have the function return on the preceeding line? Is it just so that the function name is in the first column?" "4622": "Yeah I don't know what the deal was, when I asked about inlining last night it blew up everywhere." "4733": "I was messing around with loop unrolling by hand and got massive speedups, any idea why would that be?" "4795": "Wind things down" --- name: "day248" title: "Cleaning Up Data Block Display" markers: "62": "Launch the code, build the game, recap and set the stage for the day" "159": "handmade_debug_interface.h: Reacquaint ourselves with the debug system" "381": ""We set ourselves up for success"" "400": "handmade_debug_interface.h and handmade_debug.cpp: Prune irrelevant stuff" "495": "4coder: Demo some editing movements / commands and promote 4coder's power" "584": "handmade_debug.cpp: Note how GetOrCreateDebugViewFor gives us a way to lookup the debug view for a given ID" "630": "Consider ways to develop the debug system" "1297": "handmade_debug.cpp: Reorder functions and consider how the system currently works" "1459": "Run the game and look at the debug visualisation" "1580": "Debugger: Step into CollateDebugRecords, inspect the Event data and walk through what the system is doing" "2011": "Propose cleaning up the way we build and store these debug events" "2319": "Consider no longer storing data blocks as data blocks, but making it part of a standing structure" "2617": "handmade_debug.cpp: Prevent the OpenDataBlock and CloseDataBlock from getting printed and increment events" "2857": "Run the game and see our hierarchical debug view" "2898": "handmade_debug.cpp: Make the debug view collapsible" "3371": "Run the game and try out our newly collapsible debug view" "3509": "handmade_debug.cpp: Truncate the event name in DEBUGEventToText" "3657": "Run the game and see our partially truncated event names" "3694": "handmade_debug.cpp: Check for Flags & DEBUGVarToText_AddValue and add an AddValue flag to handmade_debug.h" "3786": "Run the game and see our fully truncated event names" "3796": "handmade.cpp: Stuff all of our control variables under #if HANDMADE_INTERNAL from handmade_config.h" "3947": "Run the game and see all of our values in the debug view" "4028": "Q&A" "4053": "The "Per Frame arena space remaining" debug counter is always going down! Is this okay?" "4088": "You mentioned a book that introduces relational databases. I lost the link" "4114": "Will you re-implement the profiler?" "4246": "Casey, how do you easily implement the standard output without using the iostream library?" "4292": "Which do you prefer and why? #if #ifdef #if defined()?" "4349": "Can you tell me the version of what you just said, but for Linux (and not Windows)? I'm on Arch" "4461": "In terms of interaction with the debug settings, what do you have in mind for modifying the values? Switches or sliders?" "4488": "What does a for each loop do?" "4575": "Not related to today's topic: when do you think you will be designing your game instead of writing the engine?" "4633": "What language do you think is best for programming games?" "4724": "The handles are just int ids numbered from 0, which map to per-process fd-table in kernel space" "4751": "Will you consider using Jon's language soon? Even just for trying stuff?" "4774": "Close down, thank you" --- name: "day249" title: "Cleaning Up Debug Macros" markers: "8": "Welcome, let's jump directly into the revamping of the debug code" "44": "Recap: The debug system is relatively usable, but all names are always forced through the hierarchy system, so it creates dummy nodes for things" "79": "We also want to make the profiler functional again" "117": "handmade.cpp: Add DEBUG_PROFILE() to the debug data block" "162": "handmade_debug_interface.h: Define DEBUG_PROFILE" "370": "We have debug elements (which can exist in multiple hierarchies) and debug events (things that came to the stream and which we are trying to record)" "406": "handmade_debug.cpp: Add an empty case for DebugType_CounterFunctionList and check if using the pre-existing debug element is sufficient for the profile" "561": "handmade_debug.cpp: Check it DebugType_MarkDebugValue is still used and remove it" "678": "handmade.cpp: Check if the debug system supports nested data blocks" "795": "handmade_debug.cpp: Include the DebugType_CounterFunctionList case in the DEBUGDrawElement" "887": "handmade_debug.cpp: Remove the previously added interception call for DebugType_CounterFunctionList (the empty case)" "965": "handmade.cpp: Refine the data blocks syntax" "1390": "handemade_debug_interface.h: Rewrite the DEBUG_DATA_BLOCK in order to accomodate the changes made to the API" "1553": "Implementing the constructor for the data block begin and end" "1648": "handmade_debug.cpp: Check to see where the GUIDs are used" "1750": "handmade_debug_interface.h: Considering passing GUIDs through the RecordDebugEvent call graph" "2032": "Add "Name" to the UniqueFileCounterString(), remove BlockName from RecordDebugEvent and the debug_event struct" "2226": "Rename UniqueFileCounterString to DEBUG_NAME" "2275": "Check if Counter is used and remove it, simplifying FRAME_MARKER()" "2362": "Clean up BEGIN_BLOCK_() and END_BLOCK_() and add GUIDs to calls to RecordDebugEvent" "2429": "Clean up BEGIN_BLOCK(Name) and END_BLOCK(Name) by passing only the DEBUG_NAME(Name)" "2485": "Clean up the timed_block struct" "2595": "Clean up the TIMED_BLOCK and TIMED_FUNCTION macros" "2735": "Analyze the END_BLOCK("~timed_block") call" "3088": "Preprocess and search for "~timed_block"" "3264": "The debug code was not preprocessed because of the missing -D_HANDMADE_INTERNAL=1 switch on the command line" "3344": "Changing GUID to GUIDInit in the RecordDebugEvent macro so that it expands properly" "3391": "Remove Name from the END_BLOCK macro" "3425": "Another benefit of using a "Single Compilation Unit Build" is that if we want to preprocess a file, we can easily do it" "3572": "Temporarily remove -DHANDMADE_INTERNAL=1 switch from the build.bat file and fix other build errors on data blocks" "3721": "Q&A" "3762": "How the heck do you quickly get back into some obtuse code that you haven't looked at in 6 months?" "3828": "Wrap up. Thank you" --- name: "day250" title: "Cleaning Up Debug GUIDs" markers: "12": "Setting the stage and getting right back into cleaning up the debug layer" "141": "Fixing compile errors after reactivating the -DHANDMADE_INTERNAL switch" "190": "handmade_world_mode.cpp: Removing EntityDebugID from the DEBUG_DATA_BLOCK() call and considering adding it in a DEBUG_VALUE() call, if needed" "286": "Replacing BlockName with GUID and further cleaning up the debug code" "358": "handmade_debug_interface.h: Wrapping names that pass through the system in DEBUG_NAME()" "497": "Fixing the TIMED_BLOCK macros" "598": "handmade_render.cpp: Changing various BEGIN_BLOCK() calls to reference strings" "691": "Removing names from END_BLOCK() calls" "830": "Running after fixing compile errors" "1018": "handmade_debug.h: Deciding to simplify the debug_state struct" "1063": "handmade_debug.cpp: Checking if and where HighPriorityQueue is used, and removing it afterwards" "1119": "Removing the compiler feature from the debug system, but leaving it in place in the platform layer for the moment" "1337": "Reacquainting with the debug view system" "1492": "Breakdown of debug_view, debug_stored_event, debug_element and debug_tree" "1714": "Parsing the content of the GUID in the debug_element in order to obtain a more readable format" "1804": "handmade_debug.cpp: Hashing the strings in order for having them persistent across hot-reloads" "2146": "handmade_debug.h: Re-adding the GUID to the debug_element struct" "2262": "Storing the GUIDs in the persistent storage DebugArena" "2315": "Parsing the GUIDs to obtain FileNameCount, LineNumber and NameStartsAt" "2476": "handmade_debug_interface.h: Optimizing the UniqueFileCounterString__ macro for parsing" "2712": "Adding functions to easily retrieve the name and filename using counted strings from the debug element GUID" "2837": "Fixing compile errors" "2946": "Running and verifying the results - the parsing partially works" "3021": "handmade_debug.cpp: Reassigning the correct GUID when storing events so that they are safe across hot-reloads" "3227": "Changing the pre-storing of the GUID with the already extracted name" "3268": "Changing the separators from underscores to slashes" "3400": "Q&A" "3416": "Please use the following hash computation: HashValue = HashValue * 65599 + *Scan; (sdbm, source: http://www.cse.yorku.ca/~oz/hash.html). Simply using a sum of chars *will* produce a lot of collisions. (source: http://programmers.stackexchange.com/a/145633)" "3647": "Yes, the reasoning behind the hash is that it's used for symbols in ELF. If you think about it, symbols tend to come in clusters: i, j, k, x1, x2, x3 etc. ElfHash is designed to behave sensibly in that case" "3809": "Do you have a stream schedule?" "3866": "Actually, could you humour me and look at the disassembly for that hash function? The 65599 one? I'm curious to know how well it compiles" "4173": "what is imul, int multiply?" "4578": "Dude, you inspired me to write a handmade Windows debugger. Thanks for everything you do" "4606": "Why did you put the delta time of each frame into the input struct (Input->dtForFrame). That seemed a bit strange to me while looking through the source code today" "4633": "Why are the half-bytes of the hex value 1003fh reversed in the instruction. I could understand the bytes being reversed, but the half-bytes?" "4841": "And you want Intel to ship a unifying ISA for all GPUs..." "4940": "I'll keep that in mind" "4974": "Why was it passed in that structure? I was specifically looking for the delta time variable and that was the last place I expected it to be" "5053": "To add on, since each player has their own input struct, passing it through each one when it's going to be the same for each player seems redundant" "5139": "Wrap up. Thank you" --- name: "day251" title: "Finishing the Debug Hierarchy" markers: "45": "Run the game and see where we're at in terms of the debug hierarchy" "165": "handmade_debug.cpp: Look through how the hierarchy is currently being built" "412": "handmade.cpp: Note that the DEBUG_VALUE should have appeared in the debug view" "475": "handmade_debug_interface.h: Confirm that DEBUG_VALUE should be being set correctly" "516": "handmade_debug.cpp: Investigate why DEBUG_VALUE is not appearing as expected" "625": "Debugger: Step into a DEBUGDrawEvent call and inspect the Event" "644": ""Somebody is doing something dumb"" "677": "Debugger: Try to step into a StoreEvent call and realise that the Event is already being parsed previously" "803": "handmade_debug.cpp: Delete the GetElementFromEvent call from CollateDebugRecords and call it on demand where it's needed" "939": "Propose putting everything into the hierarchy, to avoid the constant problem of needing to decide whether Elements should go into DataBlocks or not" "1014": "handmade_debug.cpp: Make the GUID get set correctly" "1082": "handmade_debug.cpp: Comment out the GUID setting in StoreEvent" "1202": "handmade_debug.cpp: Rework how the debug groups get set" "1441": "Run the game and see that it isn't working at all" "1479": "handmade_debug.cpp: Initialise Element to 0 when making an OpenDebugBlock" "1733": "handmade_debug.cpp: Introduce debug_parsed_name and DebugParseName" "1816": "handmade_debug.cpp: Call DebugParseName and continue reworking" "2070": "Debugger: Compile and hit a first-chance exception" "2129": "handmade_debug.cpp: Remove StoreEvent call for CloseDataBlock" "2138": "Debugger: Compile and run and see that we're almost there, with possibly only a data bug" "2168": "handmade.cpp and win32_handmade.cpp: Correct the names of our DEBUG_DATA_BLOCK" "2221": "Run the game and admire our debug information" "2293": "handmade_debug.cpp: Modify the logic in GetGroupForHierarchicalName to enable correct expansion of the hierarchy" "2740": "Run the game and see that we seem to be good, besides the fact that debug values are not editable" "2804": "Lodge a complaint against Mr Five minute warning" "2812": "handmade_debug.cpp: Delete everything related to OpenDataBlock" "2840": "handmade_debug.cpp: Investigate why we cannot edit the debug values" "2945": ""C++ is awesome and always does everything wrong"" "2950": "handmade_debug_interface.h: #define DEBUG_B32 to manually specifiy that it is a boolean" "2991": "handmade.cpp: Call DEBUG_B32" "3036": "Debugger: Run the game, see that the debug values are still not editable and start to investigate why" "3134": "handmade_debug_interface.h: Provisionally introduce the notion of needing to DEBUGHandleValueEdit in DEBUG_B32 and DEBUG_VALUE" "3337": "Q&A" "3372": "Wednesday, you talked about Microsoft's Xbox process to detect which vertex was closest to another to form quads / tris / faces. Do you have the math behind that or maybe a link about it? I tried looking for it since then without any success" "3406": "Blackboard: Triface meshes and "locality"" "3973": ""It's just a full tristrip and it touches itself maximally"" "3985": "Blackboard: A perfect patch for maximum throughput, without needing to restart the tristrip" "4107": "Blackboard: Primitive Assembly Cache and Vertex Transform Cache" "4360": "Well yes, what you are now figuring out, that was my question. How does it "know" to use which vertex point to make triangles when you add them? Like, in your first grid example, how does it know not to draw a triangle from your center vertex to the upper left vertex (or any opposing vertex, for that matter)?" "4446": "Blackboard: Primitive Assembly: Triangles, Tristrips and Trifans" "4494": "Blackboard: Triangles" "4546": "Blackboard: Tristrips" "4629": "Blackboard: Trifans" "4773": "You mentioned shortly to make Handmade Hero startup quicker which is slow now because of what OpenGL has to do. How? Would think we need to load the textures first before showing Handmade Hero?" "4837": "For people who do 3D meshes, it seems there's a rule (at least for Blender, as far as I know) that using anything else than quads for topology produces rendering artifacts, so it has to be avoided. Is this because when rendering in-game everything gets split again into triangles? Ignore the Q: if what I'm asking doesn't make sense" "4982": "With OpenGL context creation, which bit is the slow bit? Is it SetPixelFormat, as it may be VS2013 that is the problem? In VS2015 this is not as slow" "5029": "shell.bat: set _NO_DEBUG_HEAP=1 in order to disable the debug heap" "5147": "Debugger: Run the game and note that the startup is now probably a little faster" "5272": "Explain the debug heap" "5326": "Close down" "5374": "Promote Handmade After Dark" --- name: "day252" title: "Allowing Debug Value Edits" markers: "92": "Recap and set the stage for the day" "187": "Consider how to proceed in making the debug values editable" "263": "handmade_debug_interface.h: Introduce DEBUGEditEvent in DEBUG_VALUE which allows setting the Event to a new value" "502": "handmade_debug_interface.h: Introduce DEBUGValueGetEventData in DEBUG_VALUE and create function prototypes of it for all the types we need" "658": "4coder: Hit a bug while doing replace-in-region from v4 to rectangle2" "874": "4coder: Hit a bug loading the same buffer twice" "1005": "handmade_debug_interface.h: Reintroduce DEBUGValueGetEventData in DEBUG_VALUE, compile, receive compile errors as expected, and rewrite those DEBUGValueGetEventData function prototypes" "1236": "Note that the Entity->Type cannot be converted because it is an enum" "1341": "handmade_debug_interface.h: Make DEBUGValueGetEventData take an Ignored value" "1518": "handmade_debug_interface.h: Introduce DEBUGEditEventData in DEBUG_VALUE and DEBUG_B32 to update the Event if needed" "1617": "handmade_debug.cpp: Consider making GetElementFromEvent write the pointer to the debug element" "1802": "handmade_debug.cpp: Implement DEBUGEditEventData" "2476": "handmade_debug.cpp: Remove DEBUGEditEventData and simplify the system so all it needs to do is check if the two pointers for the GUIDs match" "3354": ""It's a little pointer-chasey"" "3375": "Run the game and note that the values cannot be edited but that we are in good shape" "3439": "handmade_debug.cpp: Copy in the *Event DEBUGEndInteract and introduce the notion of OriginalGUID" "3731": ""Whoops, that function doesn't exist in 4coder yet, you can't call it, Casey!"" "3741": "handmade_debug.cpp: Make GetElementFromEvent store the OriginalGUID" "3902": "Debugger: Set a breakpoint in DEBUGEndInteract and see that we do hit it" "4063": "Debugger: Investigate why the OriginalGUID is not being preserved upon editing the debug element" "4143": "Moment of realisation: GetElementFromEvent will itself overwrite the GUID" "4192": "handmade_debug.cpp: Set OriginalGUID in CollateDebugRecords" "4264": "Debugger: Break into DEBUGEndInteract and find that GetElementFromEvent doesn't know the original value" "4393": "handmade_debug.cpp: Stop rewriting the GUID in StoreEvent" "4423": "Run the game and see that we can actually edit these values okay now" "4457": "handmade.cpp: Change DEBUG_VALUE to DEBUG_B32 where appropriate" "4494": "Run the game and see that some of our textures have failed to load, but that all our boolean values are now editable" "4552": "Trigger the particle system" "4584": "win32_handmade.cpp: Switch the rendering type" "4701": "handmade_debug.cpp: Ensure that we clear out the debug EditEvent when we start debugging" "4853": "build.bat: Turn on -O2 and try switching between the two renderers" "4940": "handmade_world_mode.cpp: Provide the ability to toggle the GroundChunks" "5156": "handmade.cpp: Put GroundChunksOn in the menu" "5179": "Run the game and toggle the GroundChunks" "5239": "Close this down" --- name: "day253" title: "Reenabling More Debug UI" markers: "74": "Run the game, try out the debug system and set the stage for the day" "207": "build.bat: Switch to -Od" "249": "handmade_debug.cpp: Change StartAtLastSlash to ShowEntireGUID" "346": "handmade_debug_interface.h: Consider excising the debug_id in favour of the debug_element pointer" "687": "Apologise to the DebugIDs" "805": "Run the game, note that the DebugID does work to toggle and investigate why highlighting does not work" "1013": "Debugger: Step into DEBUGDrawEvent and inspect the values being passed to InteractionsAreEqual" "1162": "handmade_debug.cpp: DEBUGDrawElement" "1233": "Debugger: Break on the InteractionIsHot call in DEBUGDrawEvent and watch the value of Generic" "1366": "Apologise to the man in the tree" "1415": "handmade_debug.cpp: Replace debug_stored_event with debug_element" "1630": "Run the game and commit an access violation" "1657": "handmade_debug.cpp: Conditionally set the Event in DEBUGInteract" "1674": "Run the game and see that our highlighting now works" "1699": "handmade_debug.cpp: Call DEBUGMarkEditedEvent in DEBUGInteract" "1761": "handmade_debug.cpp: Implement DEBUGMarkEditedEvent" "1857": "Run the game and edit the DebugDistance" "1917": "handmade_debug.cpp: Re-enable tearing" "2438": "handmade_debug.cpp: Call CreateVariableGroup in the TearValue case" "2577": "handmade_debug.h: Introduce CloneVariableGroup" "2657": "handmade_debug.cpp: Do the TearValue ItemInteraction if we're using the AltUI" "2803": "Debugger: Break into the debug system and note that it is working the way it used to work" "2916": "handmade_debug.cpp: Implement CloneVariableLink" "3200": ""We clone because we care"" "3247": "handmade_debug.cpp: Implement CloneVariableGroup" "3395": "Run the game and commit an access violation" "3525": "Hear the helicopters outside" "3541": "Debugger: Step into CloneVariableGroup and inspect the Result" "3671": "handmade_debug.cpp: Replace SubGroup with Dest->Children in CloneVariableLink" "3695": "Run the game and tear off some elements" "3844": "Q&A" "3888": "Dude's still up there, just to let you know" "3895": "The guy actually thought it was a binary tree and that he would be on the ground if he gets to the leaves..." "3936": "What is the debug code to other code ratio now?" "4040": "What happens if you try to modify a dynamic variable, e.g. player position?" "4128": "In CloneVariableGroup() ... sizeof (Name) - 1, should this be the string length, not size of pointer - 1?" "4151": "handmade_debug.cpp: Pass the correct calculation to CreateVariableGroup in CloneVariableGroup" "4234": "Wrap it up" --- name: "day254" title: "Reenabling Profiling" markers: "91": "Run the game and propose getting the profiling system back in some semblance of working order" "451": "handmade_debug.cpp: Reacquaint ourselves with CollateDebugRecords" "735": "Savour the moment" "797": "handmade_debug.cpp: Simplify CollateDebugRecords and change what gets passed to StoreEvent" "996": "Blackboard: Call Attribution" "1110": "handmade_debug.h: Make a note to store call attribution data in debug_stored_event" "1225": "handmade_debug.cpp: Implement Call Attribution" "1330": "handmade_debug.cpp: Collapse DEBUGDrawElement and DEBUGDrawEvent down to one function" "1452": "Blackboard: Sketch out the overview profiler" "1556": "handmade_debug_interface.h: Begin to implement ThreadIntervalGraph" "1703": "Run the game and see END_BLOCK being printed out" "1872": "Debugger: Hit an assertion and investigate" "1929": ""Would you be a lamb and jump me there?"" "2095": ""We just have a bug bug"" "2163": "handmade_debug.cpp: Comment out the StoreEvent calls to determine that 32MiB is not enough memory" "2343": "handmade_debug.cpp: Make GetElementFromEvent take b32 CreateHierarchy in order to conditionally do GetGroupForHierarchicalName" "2569": "handmade_debug.cpp: Introduce the notion of ProfileGroup" "2709": "Run the game and check out the debug visualisation" "2881": "handmade_debug.cpp: Make DrawProfileIn draw one frame" "4221": "Run the game and check out the correct debug visualisation" "4270": "Q&A" "4295": "handmade_debug.cpp: Convert a PointerToU32 down to CloseEvent->GUID" "4367": "What do you think of using a "call tree" to track dependencies across multi-threading?" "4413": "What command do you use to change from cutscene to game" "4419": "Tomorrow is episode 0xff!" "4429": "How do you handle tasks that run in separate threads but take longer than a frame to compute? For example, I heard that in the new Forza the rear view mirror updates at half the framerate as everything else" "4485": "WHY WAS I NOT INFORMED THAT KRAMPUS IS IN THIS GAME?" "4575": "Is talking to the chat while coding helpful to work things out?" "4611": "Do you have a problem with Santa from your childhood?" "4659": ""Santa is not good"" "4693": "I DID NOT GET A PICTURE OF KRAMPUS" "4711": "Did you consider visualizing timing using flame graphs?" "4800": "Is this software renderering? The frame time has tanked" "4843": "handmade_debug.cpp: Stop looping through every event every time" "5003": "Close down here" "5044": "Do you have a secret phobia of writing game code?" "5236": "Can we make games in GameMaker and submit them to you for the final game?" "5395": "Q: After you stop recording, beckon people to stay in the chat for a bit" "5433": ""It would be weird..."" "5442": "Q: It has to do with won_3d and an interview with him" "5489": "Q: It's not a live interview..." "5500": "Close down the stream" "5536": "Recommend Won Chun" --- name: "day255" title: "Building a Profile Tree" markers: "11": "Set the stage for the day" "32": "Problem #1: No fast way to get out the profiling information for the previous frame" "66": "Problem #2: In order to print out the profile view we need some concept of the nesting of calls inside one another" "241": "Blackboard: Profile Queries" "403": "Hype the new version of 4coder" "472": "handmade_debug.cpp: Enable the profiler" "492": "Run the game and hit an InvalidCodePath as we overflow the PushBuffer of the renderer" "865": "handmade_debug.cpp: Disable the profiler" "902": "handmade_debug.h: Add StoredEventCount, ProfileBlockCount and DataBlockCount to debug_frame" "992": "handmade_debug.cpp: Increment these values in StoreEvent and CollateDebugRecords" "1057": "handmade_debug.cpp: Print out these values" "1125": "Run the game and see what those numbers look like" "1300": "Consider how to process this data" "1471": "handmade_debug.h: Introduce debug_profile_node" "1801": "handmade_debug.cpp: Make DrawProfileIn take a debug_profile_node and work through how to use it" "2355": "handmade_debug.cpp: Make the DrawProfileIn call in DEBUGDrawElement take RootProfileNode" "2635": "handmade_debug.h: Use debug_stored_events in debug_profile_node" "2845": "Be Mr Cheesy - Mr Cheesepants, Cheese man" "2883": "handmade_debug.cpp: Set debug_stored_event *Node to the result of StoreEvent (via *StoredEvent) and then immediately rewrite it" "3594": "Run the game and see that we're never adding anything to the RootProfileNode" "3634": "handmade_debug.cpp: Conditionally set the ParentEvent in BeginBlock" "3921": "handmade_debug.cpp: Setup the children in BeginBlock" "3995": "Debugger: Step into DrawProfileIn and inspect the RootEvent" "4086": "handmade_debug.cpp: Correctly set the Node's Duration" "4248": "Run the game and admire the bizarre results" "4271": "Q&A" "4311": "Need to find a whole os is that we get a taste again... For some! Implementing merge?" "4320": "Will the day-counter overflow tomorrow, or will The Variable provide more bits for us?" "4337": "How are you going to celebrate Handmade Hero episode 0xFF?" "4403": "Soon enough we will need 10 bits to store the day counter!" "4480": "We may even need 11 bits!" "4500": "How long will it take me to get your "flow" of coding? 40 years?" "4524": "What kind of data is the profiler intended to display?" "4586": "Do you know what the total line count is at?" "4615": "Will you be able to turn on / off profiling for certain functions with the debug UI?" "4656": " A big part of the slow startup for me is that the ModeArena is cleared to zero by default at the moment. That's about 256MB" "4719": "win32_handmade.cpp: Set GlobalRenderingType to software" "4807": "Run the game and witness a very slow fade" "4871": "build.bat: Stop linking with opengl32.lib" "4922": "win32_handmade.cpp: Switch back to OpenGL and witness a longer startup" "4968": "Wind down, wrap it up" "5027": "Anticipate new 4coder" --- name: "day256" title: "XBox Controller Stalls and Fixing GL Blit Gamma" markers: "8": "Hype 4coder 4.0.2 super" "156": "Recap and set the stage for the day" "189": "Run the game and view the current state of the profiler" "292": "handmade_debug.cpp: Review the profiling code" "520": "handmade_debug.cpp: Note that we are using the EndClock value before it's been written" "573": "handmade_debug.cpp: Compute that Duration in CollateDebugRecords and correctly set the ClockBasis" "691": "Run the game and view our more plausible profile result" "764": "handmade_debug.cpp: Reenable and rewrite the text on hover" "818": "Run the game and view this text on hover" "879": "Blackboard: Pointer alignment and random picking from an array" "1026": "handmade_debug.cpp: Make the Colors array be a non-multiple of four" "1067": "Run the game and see our different zones in the profiler" "1153": "handmade_render_group.cpp: Add SortBias to the object_transform so the SortKey automatically takes it into account" "1238": "On writing TODOs" "1333": "handmade_debug.cpp: Introduce Transforms in DEBUGTextOp" "1431": "Run the game and note that our problem hasn't been fixed" "1453": "handmade_debug.h: Add Transforms to the debug_state" "1555": "handmade_debug.cpp: Initialise the Transforms in DEBUGStart" "1618": "handmade_debug.cpp: Pass BackingTransform to the PushRect calls in DrawProfileIn" "1707": "Run the game and view our profiler" "1771": "Blackboard: What the profiler is showing us may be happening after the point SwapBuffers is called" "2058": "Point out how useful profiling is" "2203": "win32_handmade.cpp: Investigate what's happening in our input processing" "2393": "Run the game and note that we need the ability to narrow in on a profile region" "2442": "win32_handmade.cpp: Comment out the "Input Processing" block" "2466": "Run the game and discover that the XBox controllers are taking 2,000,000 cycles to poll" "2514": "Describe and consider how to work around a well-known XInputGetState bug when polling XBox controllers" "2745": "win32_handmade.cpp: Introduce XBoxControllerPresent, assume they're all plugged in at startup and stop polling for them when we realise they're not" "2924": "Run the game and see none of that controller polling nonsense" "3005": "Discover that the software renderer does not draw the profiler properly" "3084": "handmade_opengl.cpp: Make glTexImage2D take GL_SRGB8_ALPHA8" "3165": "Run the game and see that that was the problem" "3220": "Explain how gamma is treated in the renderer" "3331": "Note that we need to reserve one texture at startup in case we would like to do OpenGL bitmap display" "3378": "Demo the bug with switching between the renderers" "3447": "win32_handmade.cpp: Introduce OpenGLReservedBlitTexture and set one of them Win32InitOpenGL" "3537": "Run the game and see that we now no longer have that bug, but do have a bug with pixel centers for the fonts" "3640": "Q&A" "3668": "insobot What do you think of Microsoft's Tay bot?" "3682": "cmuratori Oh wow. I guess i should say? Wow, thought i came" "3690": "Q: Can't remember what OpenGL considers the center of the pixel...?" "3770": "Is romp just a synonym for clobber?" "3776": "Will the opening cutscene be narrated?" "3792": "Could you elucidate further on the waiting for VSync in the profiler?" "3942": "I actually prefer the fonts that the software renderer produces. Is there anything we can do to make them look that way in GL?" "3996": "Recommended entry-level programming language for aspiring game devs?" "4254": "Is there anything that can be done to help make it easier to hover / click on the debug visualization?" "4326": "popcorn0x90 You can implement most of it, replacing most of" "4333": "Are all the textures transferred every frame?" "4480": "In the debug UI will we be able to click on a frame and have it blit that frame?" "4542": "Could you explain in what consist the dynamic resolution? Texture rescale, viewport rescale?" "4576": "Are we going to have it auto-pause on long frames?" "4598": "What about checking for memory leaks?" "4658": "At what point would you make the transition from a more basic language like JavaScript over to a language like C?" "4915": "Sorry, have a fail-safe to see when we stutter to pause the system and debug it" "4985": "Close" "5042": "Promote 4coder" --- name: "day257" title: "Cleaning Up Some Win32 Issues" markers: "22": "Set the stage for the day" "119": "build.bat: Introduce and check for HANDMADE_STREAMING environment variable" "415": ""Where are you, Mr. Environment Variables?"" "533": "Double check to make sure that we can still stream" "575": "Delete a bunch of stuff we no longer use" "853": "handmade_platform.h: Rename PointerToU32 to U32FromPointer and call it where needed, in order to prevent GCC and clang from complaining" "1080": "Run the game and ensure that it does run" "1153": "win32_handmade.cpp: Remove the fader" "1411": "Consider removing the multi-threaded OpenGL contexts" "1523": "Run the game and point out a bug in the profiler upon hot-reloading" "1823": "Debugger: Manually write xor instructions into memory" "1965": "Run the game and verify that the strings are getting messed up" "2065": "handmade_debug.cpp: Fix the string handling" "2450": "Run the game, test the hot-reloading to see that the strings do remain stable, but crash" "2524": "Debugger: Inspect the Thread and find that the OpeningEvent does not have to be valid" "2599": "Q: Why did we make the GlobalDebugTable a static buffer?" "2745": "win32_handmade.cpp: Make the GlobalDebugTable in here be the authoritative one and rewrite how it gets collated" "3163": "Run the game and twiddle it a little bit" "3244": "Investigate what is wrong with our profile" "3690": "win32_handmade.cpp: Conditionally clear the debug event array if the game failed to load" "3759": "Run the game and resume our investigations" "3844": "Debugger: Step into BeginBlock and inspect the DebugState" "4181": "Debugger: Inspect the events' GUIDs and break into EventsMatch" "4218": ""I don't care about you"" "4273": "handmade_debug.cpp: Temporarily Assert that EventsMatch and inspect the Events when we hit that assertion" "4464": "handmade_debug.cpp: Note that the Event is transitory and instead use StoredEvent for now" "4576": "Debugger: Inspect the Events and StoredEvent" "4595": ""Something very strange is afoot"" "4652": ""So complicated. I rather enjoy it, though"" "4656": "handmade_debug.h: Make open_debug_block not store the entire debug_event but instead just store the data we want" "4824": "Run the game and see that we're still losing our profile" "4879": "Q&A" "4896": "Would it be reasonable to separate the debug UI into a separate program that communicates with the game over pipes / sockets? The game won't hold the debug data and won't waste cycles on debug collation, debug rendering; if game crashes, you can still inspect frames, or even save them to the disk independently of the game running" "4989": "You are referring to GlobalDebugTable outside a HANDMADE_INTERNAL guard, when you initialize it in UpdateAndRender" "5005": "Casey, your stream overlay disappeared at some point this evening. I'm pretty darn sure it might have happened out of protest when you removed the beautiful fade, so it could be worth reimplementing that, if only in the interest of overlay stability" "5019": "How are you finding modular editing so far?" "5079": "handmade.cpp: Initialise GlobalDebugTable inside HANDMADE_INTERNAL" "5110": "Why not use DebugBreak instead of *(int*)0=0 which will allow you to step over the assertion if you really want but will still trigger the breakpoint" "5131": "The Handmade twitter account says tomorrow is an off day" "5137": "What exactly is modular editing?" "5169": "When you're writing your own renderers and stuff, do you go for a left-handed coordinate system or right-handed (for vector-matrix multiplications, etc.), and why?" "5196": "Something I noticed when you disabled the trees rendering, the white dot used to resize the profiler view is hard to see over a light background, like the text was hard to read before adding a shadow" "5262": "Do you find that commentating as you work helps you reason or helps you overall when programming?" "5283": "Do you think 4coder is good enough to switch to coming from emacs? Or are you finding it's missing some stuff yet?" "5399": "And vertical- / block-kill / -selection?" "5432": "Off topic: I noticed that pragma pack will change the alignment of the struct. Is there a way of keeping the original alignment?" "5448": "Could you share your 4coder_custom.cpp?" "5542": "Do you think it would be neat to save a DebugUI "layout" with torn elements open as they were last?" "5582": "I include it in 4coder at the $10 level" "5610": "Is it possible to use with the $5 build?" "5629": "Call it a day" "5666": "Promote 4coder" --- name: "day258" title: "Fixing Profiling Across Code Reloads" markers: "39": "handmade.prj: Move the .prj files from the code to the root directory" "71": "Recap and set the stage for the day" "158": "Run the game, do a hot-reload and note that the profile is busted" "228": "Explain the debug collation situation in terms of multithreadedness" "525": "Consider how to potentially solve the problem" "739": "win32_handmade.cpp: Flush all the queues, do FrameEnd and then finally do the hot-reload" "898": "Run the game, attempt to hot-reload, and hang" "954": "Debugger: Investigate what's going on here" "1072": "Explain the bug: Upon hot-reloading, we go back through the collation code because there was no collation code to call" "1147": "win32_handmade.cpp: Try loading the game code multiple times during collation" "1303": "Run the game and try hot-reloading" "1341": ""How about you actually check to see if it's loaded, Muratori!"" "1354": "win32_handmade.cpp: Fix the LoadTry loop" "1383": "Run the game and try that one more time" "1412": "Debugger: Investigate what's going on" "1485": "Blame it on the code" "1581": "handmade_cutscene.h: Introduce struct cutscene and enum cutscene_id" "1766": "Run the game and find that we're not safe across reloads in the cutscene mode" "1829": "Debugger: Break on Win32UnloadGameCode and inspect the GlobalDebugTable" "2040": "A thought" "2064": "win32_handmade.cpp: Disable the EventRecording while we reload" "2358": "win32_handmade.cpp: Enable the EventRecording initially" "2391": "Run the game and..." "2423": "Admire the lovely profiler" "2455": "build.bat: Switch to -O2 and see how the profiler fares" "2516": "Happy puppy" "2523": "Q&A" "2560": "Not sure if this was asked before but is it worth to use static_cast instead of a C-style cast that does static_cast, dynamic_cast and reinterpret_cast, if you know that you only need the first?" "2612": "Demo: C-style cast" "2899": "Demo: C++ dynamic_cast" "3089": "How exactly did they mess up casting in C++?" "3201": "dynamic_cast will return 0 if it fails" "3219": "Is the debug view for bitmaps working again?" "3255": "For string manipulation, is there a library worth to use in C/C++? I could do it with Python but I'd like to use C" "3297": "You are spending a lot of time on debug tools before you need them. Is it going to be worth it?" "3487": "Speaking of string libraries, what kinds of things do you think should be in a good string library?" "3576": "expixel: Hand banana hero. You rock" "3580": "Andrew Chronister: "Insobot is a national treasure"" "3601": "Does using VirtualAlloc and reserving a lot of memory upfront count?" "3676": "Well I meant using MEM_RESERVE then MEM_COMMIT so that you can append quickly without the copy" "3700": "Go eat dinner" "3744": "Promote Martins Mozeiko" "3785": "Mention HandmadeCon 2016" "3826": "Promote 4coder" --- name: "day259" title: "OpenGL and Software Renderer Cleanup" markers: "8": "Recap and set the stage for the day" "90": "Run the game and demonstrate how we'd like to develop the profiler" "370": "handmade_debug.cpp: Look through the profiler code" "535": "handmade_debug.cpp: Use ThreadOrdinal to set the LaneIndex" "612": "Run the game and view the profiler information in LANES" "731": "handmade_debug.cpp: Investigate why the background colour is incorrect in the software renderer" "882": "handmade_debug.h: Introduce UITransform layer" "938": "Run the game, view the profile and investigate why it is pink" "1041": "handmade_render.cpp: Make DrawRectangle SIMD and do alpha blending" "1561": "Debugger: Break on FillRect and find that it and ClipRect never intersect" "1720": "handmade_render.cpp: Set FillRect earlier" "1757": "Debugger: Step through and inspect the rectangle values" "2070": "handmade_render.cpp: Use structured art to help debug this" "2117": "Debugger: Inspect the Blended values" "2202": "handmade_render.cpp: Multiply Color by 255 in order to get it into the correct space" "2262": "Run the game, see that the colours are incorrect and investigate why" "2511": "handmade_render.cpp: Square the ColorValues up front" "2668": "Run the game and see that the colours are now correct" "2719": "win32_handmade.cpp: Reenable our threads and view the profiler" "2766": "handmade_opengl.cpp: Take account of the 1-pixel border in OpenGLRectangle" "2970": "handmade_opengl.cpp: Pass the corrected coordinates to OpenGLRectangle in OpenGLRenderCommands" "3107": "Run the game and see that the fonts look more correct" "3180": "GitHub: Close issue #15" "3256": "win32_handmade.cpp: Check for OpenGLSupportsSRGBFramebuffer in Win32SetPixelFormau" "3353": "handmade_opengl.cpp: Make OpenGLInit take FramebufferSupportsSRGB" "3474": "Run the game and admire how close we match" "3501": "Fight the urge to go back and correct it" "3547": "handmade_opengl.cpp: Support the ARB versions of our extensions" "3685": "GitHub: Close issue #8" "3779": "Debugger: Break into OpenGLGetInfo and see what extensions this GPU supports" "3880": "Q&A" "3937": "I've implemented a quick and dirty flame graph for Handmade Hero" "3983": "Is the stream being off tomorrow an April Fool's joke?" "4000": "What happened to the software rendered performance? It was running at 30 FPS a few months ago! Even without -O2 it was pretty decent" "4027": "build.bat: Switch to -O2 and watch the profiler" "4141": "win32_handmade.cpp: Switch to Win32RenderType_RenderSoftware_DisplayGDI and again watch the profiler" "4272": "So let me get this straight, modern PCI-E connections have several GB/s of bandwidth and yet it takes several frames to upload a texture for the backbuffer?" "4400": "Go eat some dinner" --- name: "day260" title: "Implementing Drill-down in the Profiler" markers: "58": "Run the game and consider how to develop the profiler" "310": "handmade_debug.cpp: Make DrawProfileIn do PushRectOutline instead of PushRect" "356": "handmade_render_group.cpp: Introduce a PushRectOutline that takes the same arguments as PushRect" "394": "Run the game and see that the outlined rectangles don't seem to be correct" "564": "Debugger: Step into PushRectOutline and inspect its values" "763": "handmade_render_group.cpp: Make PushRectOutline use the thickness" "820": "handmade_debug.cpp: Get that thickness back in there" "843": "Run the game and view the profiler" "866": "handmade_debug.cpp: Introduce DrawProfileBars" "1161": "handmade_debug.cpp: Call DrawProfileBars in DrawProfileIn" "1211": "Run the game and see that the profile view is the same" "1219": "handmade_debug.cpp: Call DrawProfileBars recursively" "1267": "Run the game and view the entire call stack in the profile" "1322": "handmade_debug.h: Introduce MouseTextStackY to enable us to see information for multiple debug elements" "1408": "Run the game and see this information" "1458": "handmade_debug.cpp: Introduce GetLineAdvance to give us a more robust way to write multiple lines" "1610": "Run the game and see our correctly spaced lines" "1641": "win32_handmade.cpp: Increase the PushBufferSize" "1677": "Run the game, view the profiler and consider implementing zoom" "1852": "handmade_debug.cpp: Begin to implement zoom" "1911": "handmade_debug.h: Introduce debug_view_profile_graph" "2072": "handmade_debug.cpp: Provide the ability to set RootNode based on a search" "2775": "handmade_debug.h and handmade_debug.cpp: Provide the ability to set the profile graph root for zooming" "3178": "Run the game and try out the zoom" "3210": "Debugger: Break into DEBUGEndInteract and inspect the values upon zooming" "3672": "Debugger: Break on ZoomInteraction, inspect the values and find that we're currently picking the wrong Frame" "3886": "handmade_debug.cpp: Search for the correct Frame to set the RootNode" "4018": "Run the game and successfully try out the beautiful zoom" "4168": "Q&A" "4211": "Are you as productive in a single 8 hour period as you are on the show over 8 sessions?" "4238": "Do you have that in your current game at work?" "4254": "Is our debug tooling sophisticated enough to detect OS slowness, i.e. problems with heap / mem performance, etc?" "4394": "When doing playback, is the debug info showing the past CPU info?" "4429": "Only in C/CPP?" "4437": "What type of game is this, e.g. FPS, RPM etc?" "4445": "Yes profiler!" "4450": "I discovered why I didn't see the font rendering. I'm on a 2560 x 1440 screen with 200% DPI scaling. Do I have to use a specific resolution to make it work?" "4499": "Was there a factor in not implementing moving backwards in the threading system?" "4647": "Call it" "4700": "Promote 4coder" --- name: "day261" title: "Changing to Static Frame Arrays" markers: "108": "handmade_debug.cpp: Initialise the ProfileGraph dimensions to something relatively large" "241": "Run the game, see the profile at a more useable default size and set the stage for the day" "342": "handmade_debug.cpp: Introduce DrawFrameBars which draws stacked bars for multiple frames" "955": "handmade_debug.cpp: Call DrawFrameBars rather than DrawProfileIn" "1037": "handmade_debug.cpp: Cap the FrameIndex" "1082": "Run the game and see our stack" "1088": "handmade_debug.cpp: Increase the FrameCount to 10" "1250": "handmade_debug.cpp: Just set the RootNode to be the OldestEvent" "1323": "handmade_debug.cpp: Increase the FrameCount to 128" "1338": "Run the game and see a more granular view of what's happening over time" "1476": "handmade_debug.h: Remove debug_frame_region and MAX_REGIONS_PER_FRAME" "1558": ""None of that's a thing"" "1568": "handmade_debug.h: Introduce debug_element_frame to allow us to track and time events" "1867": "handmade_debug.h: Introduce FrameOrdinal and MostRecentFrameOrdinal and make functions in handmade_debug.cpp use it" "2289": "handmade_debug.cpp: Work on FreeFrame and FreeOldestFrame, and rework NewFrame as InitFrame" "2892": "handmade_debug.cpp: Introduce IncrementFrameOrdinal and GetCollationFrame" "3092": "handmade_debug.cpp: Work through compile errors" "3708": "Run the game and see that it is (almost) working" "3768": "Debugger: Break on FreeFrame and inspect the ordinals" "4173": "handmade_debug.cpp: Conditionally do a FREELIST_DEALLOCATE in FreeFrame" "4378": "handmade_debug.cpp: Scrutinise FreeFrame and do a ZeroStruct on *ElementFrame" "4488": "Run the game and reiterate the fact that we're leaking memory" "4585": "Q&A" "4630": "Do you need to wrap that + FrameOrdinal in the FreeFrame function?" "4668": "handmade_debug.cpp: Assert that FrameOrdinal is less than DEBUG_FRAME_COUNT" "4748": "handmade_debug.cpp: Keep track of the FreedEventCount" "4795": "Run the game, crash and find that we're freeing one more event than we're storing" "4870": "handmade_debug.cpp: Remove a FREELIST_DEALLOCATE" "4896": "Rebuild and run and find that the bug's gone" "4968": "I'm a bit behind on Handmade Hero, but do you typically bypass (for something like off-stream coding) all the simplified things like rendering a bitmap like how you were doing (DrawBitmap, like on episode 39), and go straight to the renderer? But as well as other things like structured assets and the like?" "5127": "Thoughts on using a static array instead of the lists?" "5176": "insobot had this to say today: "Inheritance and encapsulation two best inventions of mankind". Discuss" "5191": "Do you prefer to use modulo or masking for circular indexing? Do compilers replace modulos with bitwise-and if the operand is power of 2 -1?" "5301": "Are we still doing the marathon stream to account for the Q&A Monday madness?" "5313": "The profiler code you had running several weeks ago, what happened to it? Some of the things you had implemented like the multiple lanes seemed to have disappeared" "5347": "handmade_debug.cpp: Reenable the profile lanes" "5435": "Run the game, see the multiple lanes, enable the software renderer and crash" "5470": "handmade_debug.cpp: Disable the recursion for now and run the game" "5559": "What if you aren't really learning from Handmade Hero? Where I've gone through episodes 1-28 about four times and I thought I knew how to do so. I tried to make the simplified win32 layer to get to the independent layer, and I found that I couldn't do it. The documentation was rough and I forgot what things did what. What would you say to people who find that they aren't learning?" "5729": "handmade_debug.cpp: Switch from DrawProfileIn to DrawFrameBars and view the profiler" "5770": "Call it" "5862": "Promote 4coder" --- name: "day262" title: "Drawing Multi-frame Profile Graphs" markers: "64": "Recap and set the stage for the day" "209": "Apologise to folks not on the 4coder bandwagon yet" "217": "handmade_debug.cpp: Consider how to unify Element creation" "626": "handmade_debug.h: Add RootProfileElement to debug_state and pass that down the profiler system" "878": "Run the game and make sure that it works" "986": "Debugger: Step into RootProfile and erroneously follow the ParentGroup path" "1040": ""Arrrgggghhhhhh"" "1092": "Make this a very quiet, dignified edit" "1104": "handmade_debug.cpp: Do AddElementToGroup in the CreateHierarchy path" "1127": "Run the game and see that we're in better shape" "1161": "handmade_debug.cpp: Simplify the ViewingElement code using RootProfileElement" "1242": "Opine the low resolution" "1263": "handmade_debug.cpp: Simplify DrawFrameBars" "1571": "Blackboard: How the events are stored" "1713": "handmade_debug.h: Consider doing StoreEvent directly into the Element, without adding it to a Parent in CollateDebugRecords" "1831": "Blackboard: Why this might not work" "1932": "handmade_debug.cpp: Use debug_profile_node in DrawFrameBars" "2062": "Run the game and stress test the profiler" "2367": "handmade_debug.cpp: Switch to DrawProfileIn and make it take a debug_element RootElement" "2493": "Run the game and view the profiler with the old display" "2538": "Blackboard: Gracefully handling multiple events on a single frame" "2720": "handmade_debug.h: Remove AggregateCount from debug_profile_node and pack it a little differently" "2892": "handmade_debug.h: Remove TotalClocks from debug_element_frame" "3012": "handmade_debug.cpp: Introduce GetTotalClocks in order to compute TotalClock on demand" "3233": "Run the game and make sure the profiler still works" "3244": "handmade_debug.cpp: Space the EventRects based on the TotalClock" "3518": "Run the game and view our beautiful profiler" "3573": "Q&A" "3602": "Relationship status it's complicated for the movement to be it's own main function inside?" "3690": "Reasons performance was so bad with the new debug view? Isn't this still way fewer tris than a typical 3D game? Is the framerate reasonable if you switch to solid rectangles vs outlines?" "3836": "Will you make the UI immediate mode?" "3844": "Will the debug graphing update even if the game is paused?" "3868": "Right now the outlines on the profiler overlap each other. Makes it a little harder to make out the colors (or the change from one to the other). The obvious solution would be to draw them with a slight offset from the last each time, but are there any problems with that once the rectangles get really small?" "3907": "Is our current timestep code framerate independent? Will the game's simulation run the same at any framerate?" "4014": "Are we going to do the batch way then?" "4043": "(Off-topic) Have you ever defined structures inside of functions?" "4157": "Is there any advantage to making physics dependent on framerate other than convenience?" "4278": "Wrap it up" "4342": "Promote 4coder" --- name: "day263" title: "Adding a Debug Frame Slider" markers: "49": "Run the game and set the stage for the day" "116": ""You feel me, dawg?"" "167": "handmade_debug.cpp: Introduce case DebugType_LastFrameInfo and _DebugMemoryInfo and tie them into the system" "372": "handmade_debug.cpp: Introduce BasicTextElement" "470": "Hype 4coder and demo some indentation issues" "564": "Compile and run and find that BasicTextElement does work" "590": "handmade_debug.cpp: Propagate BasicTextElement" "632": "handmade_debug_interface.h: Define our new DebugTypes and DEBUG_UI_ELEMENT" "764": "Run the game and view the profiler" "790": "handmade_debug.cpp: Investigate why the DebugTypes appear in reverse order" "876": "handmade.h: #define DLIST_INSERT_AS_LAST" "954": "handmade_debug.cpp: Make AddGroupToGroup call DLIST_INSERT_AS_LAST" "987": "handmade_debug.h: Add ViewingFrameOrdinal to debug_state" "1068": "handmade.cpp: Add a DEBUG_DATA_BLOCK "Debug Control" for a FrameSlider" "1144": "handmade_debug.cpp: Implement DebugType_FrameSlider" "1324": "handmade_debug.cpp: Introduce DrawFrameSlider" "1571": "Run the game and see that we did totally mess it up" "1580": ""Nice work, Muratori. You're off the team"" "1585": "handmade_debug.cpp: Iterate through the for loop in DrawFrameSlider" "1630": "Song: 'Too Many Frames' by Casey Muratori" "1701": "handmade_debug.cpp: Make ViewingFrame yellow, the color of urine" "1848": "Run the game, view the FrameSlider and explain what will happen when we run out of per-frame arena space" "1969": "handmade_debug.cpp: Switch to a smaller SubArena for the debug information" "2001": "Run the game and hit an assertion when we have insufficient memory to store the debug data" "2132": "handmade_debug.cpp: ZeroStruct the Frame" "2154": "Run the game and watch the FrameSlider as we run out of space to store the debug data" "2282": "handmade_debug.cpp: Provide the ability to interact with the FrameSlider" "2523": "Run the game and crash upon interacting with the slider" "2540": ""Who wrote this ridiculous code?"" "2550": "handmade_debug.cpp: Put the interaction code in the correct place" "2581": "Run the game and interact with the slider" "2618": "handmade_debug.cpp: Replace MostRecentFrameOrdinal with ViewingFrameOrdinal" "2759": "Run the game and find that we can pick the ViewingFrame with the slider, but that the profiler expands weirdly" "3014": "Run the game and investigate why ToggleExpansion is happening" "3212": "handmade_debug.cpp: Conditionally set MostRecentFrameOrdinal if we're paused" "3250": "Run the game and admire the profiler" "3313": "handmade_debug.cpp: Implement the ability to pause the profiler" "3450": "Run the game and try pausing the profiler" "3501": "Demonstrate the fact that we track all of the data" "3600": "Q&A" "3631": "How much would it cost to save draw buffer snapshots so when you pause you can show the visual state it was in, or maybe save enough data to recentre the frame?" "3789": "It is impossible to keep the entire codebase in mind when developing a larger project? How does this impact "code design" decisions in Handmade Hero? What about other, larger projects (e.g. AAA titles)?" "3904": "Originally by Scykoh: "Is the engine portion expected to be the largest chunk of the Handmade Hero project?"" "4015": "Can you please explain again the problem with texture loading? Why does it not work occasionally?" "4074": "Wrap it up and glimpse into the future" --- name: "day264" title: "Adding Buttons to the Profiler" markers: "39": "Recap and set the stage for the day" "143": "handmade_debug.cpp: Switch to using the full memory arena" "249": "handmade_debug.cpp: Rework DEBUGDrawElement with the ability to switch an Element's type" "1077": "Run the game and see that nothing has changed" "1099": "handmade_debug.cpp: Introduce NullEvent to ensure that Events remain printed when their data is null" "1226": "Run the game and see our more pleasant profiler" "1276": "handmade_debug.h: Add DebugInteraction_SetElementType" "1326": "handmade_debug.cpp: Sketch out the call sites for BeginButtonRow, BooleanButton, EndButtonRow and ActionButton" "1676": "handmade_debug.cpp: Introduce ZoomRootInteraction and loft out this functionality into SetElementTypeInteraction" "1861": "handmade_debug.cpp: Implement the Button functions" "2200": "handmade_debug.cpp: Introduce BeginRow and EndRow to automatically wrap lines" "2427": "handmade_debug.cpp: Set the Root to 0" "2452": "Run the game and see that we can't interact with Threads or Frames" "2470": "handmade_debug.cpp: Implement the SetElementType case" "2735": "Run the game and successfully switch between Threads and Frames" "2747": "handmade_debug.cpp: Introduce AdvanceElement to handle spacing and line breaks" "3139": "Run the game and see that we're a little closer to correct" "3189": "handmade_debug.cpp: Make AdvanceElement aware of line heights" "3335": "Run the game and see our correctly carriage-returned information" "3396": "handmade_debug.cpp: Indent in AdvanceElement rather than EndElement" "3504": "handmade_debug.cpp: Make BasicTextElement more responsive" "3614": "Run the game and see the highlighting on hover" "3743": "Q&A" "3803": "(Not a serious question) Why not just import npm and use left pad to indent the strings?" "3832": "I think you were selecting the ground as an entity?" "3846": "[see Resources, John W. Peterson]" "3929": "You know how if you add 1 letter to HAL you get IBM? Did you know if you add one letter to VMS you get WNT?" "3955": "So this interface system is a very simple immediate mode design?" "4008": "Why there are some blue lines outside the profile window sometimes?" "4137": "VS2015, you can use clang as a compiler" "4197": "Are you using clang-cl?" "4243": "You were mentioning before about objects arising as a natural consequence of properly engineered code as the system requires. But do you do not mean a C++ object? So what do you mean as an object?" "4274": "handmade_render_group.h: Demonstrate how "objects" fall naturally out of the code" "4570": "You have a typo in the comment for object_transform" "4634": "Close it down" --- name: "day265" title: "Cleaning Up the UI Layout Code" markers: "1": "Welcome to this special day" "98": "Recap and set the stage for the day" "294": "handmade_debug.cpp: Implement a pause interaction with the FrameSlider" "411": "handmade_debug.h: Add DebugInteraction_SetUInt32" "512": "handmade_debug.cpp: Add another action button for oldest frame" "624": "handmade_debug.cpp: Turn SetElementTypeInteraction into a generic SetUint32Interaction" "1594": "Run the game and see that we are still working" "1698": "handmade_debug_ui.cpp: Pull out the user interface functions from handmade_debug.cpp" "1852": "handmade_debug_ui.h: Pull out the user interface structs from handmade_debug.h" "2200": "A few words on dividing files up" "2229": "Anticipate a programming world without files" "2287": "handmade_debug_ui.cpp: Remove the "DEBUG" prefix from everything" "2468": "handmade_debug_ui.cpp: Introduce BeginLayout and EndLayout in order to make the layout system more robust" "2723": "A few words on the expediency of compression oriented programming" "2795": "handmade_debug_ui.h: Add LineInitialized to the layout struct" "2911": "handmade_debug_ui.cpp: Use LineInitialized in BeginLayout, EndElement and AdvanceElement" "3100": "Run the game and see that our indentation bugs are gone" "3208": "handmade_debug_ui.cpp: Make the buttons look like buttons" "3643": "Run the game and admire our new buttons" "3691": "Q&A" "3729": "Remember to include your new casey_custom in the repo!" "3754": "Spoilers. Holy *** I managed about two months, the plane are reflected when no window currently has the intro?" "3782": "Could you explain your "poor man's lambda"? How it works, how it is like a lambda and how it is not?" "3928": "handmade_debug.cpp: Demonstrate "poor man's closure", or deferring things until later" "4071": "Do you ever turn on unused function / variable warnings?" "4082": "I am currently working on a 3D OpenGL project and implementing collision detection. I've been introduced to the idea of changing my vector space so my character is a perfect unit sphere (which should make collision detection easier). Do you have any opinion on this approach?" "4131": "Blackboard: Using a sphere for collision detection" "4230": "Close this up" --- name: "day266" title: "Adding a Top Clocks Profile View" markers: "95": "A few words on using third-party debugging tools or reusing ones own across projects" "194": "Launch the game and set the stage for the day" "428": "handmade_debug.cpp: Provide the ability to print debug elements in descending order of cycle counts" "589": "stb_truetype.h: Delete" "620": "handmade_sort.cpp: Pull out the sort code from handmade_render_group.h and handmade_render.cpp" "892": "handmade_debug_interface.h: Add DebugType_TopClocksList" "954": "handmade_debug.cpp: Introduce DrawTopClocksList" "1463": "handmade_debug_ui.cpp: Introduce GetBaseline" "1546": "handmade_debug.h: Introduce debug_element_add_op for more fine-grained control of how elements are profiled" "1871": "Run the game and view our DrawTopClocksList ouput" "1971": "handmade.cpp: Do TopClocksList by default" "2055": "handmade_debug.cpp: Darken the list's background" "2187": "handmade_debug.cpp: Just print out the elements' names" "2249": "Note that the Win32 Message Processing takes drastically longer when the mouse is moved" "2314": "handmade_debug.h: Add Sum to debug_statistic" "2483": "handmade_debug.cpp: Provide DrawTopClocksList the ability to print out percentages" "2813": "handmade_debug.cpp: Prepare DrawTopClocksList for sorting" "3104": "Run the game and see our sorted TopClocksList" "3164": "handmade_debug.cpp: Add the Count and Percentage to the list" "3303": "Run the game and view our TopClocksList" "3371": ""We won't add up to 100%"" "3480": "Q&A" "3562": "Can I avoid taxation by reinvesting into capital gains?" "3584": "Why won't we add to 100%?" "3642": "How would you self-update an exe? Right now I have a second exe that copies a file that overwrites the current exe. So main exe calls updateme.exe, closes itself, updateme sleeps for 1/2 second, then copies... There's gotta be something smarter" "3687": "Can the percentage support a decimal place?" "3706": "handmade_debug.cpp: Print the percentage as a float" "3772": "How may you go about investigating the cycle count increase for the Input Processing when the mouse is moved?" "3829": "Admire the profiler" "3967": "win32_handmade.cpp: Bring PeekMessage out of the while condition and put it in a TIMED_BLOCK" "4098": "Owl of Shame Moment: The platform code does not get dynamically reloaded" "4141": "Compile and run and see PeekMessage in the profiler" "4162": "handmade.cpp: Move the FrameSlider into the Profile block" "4275": "%5.2f" "4311": "My problem is the exe downloads a new exe, then I want it to replace itself, but I can't delete the running exe or even rename it while it's running. I'm fine with the game going down and coming back up, it's for updating players, not for development" "4395": "win32_handmade.cpp: Implement the ability to replace and auto-reload a running executable" "4794": "Internet: MoveFile" "5249": "Try to replace handmade.exe with notepad.exe" "5460": "win32_handmade.cpp: Fix the condition of Win32TimeIsValid" "5650": "Try to replace handmade.exe with ColorCop.exe" "5716": "Debugger: Try to launch and kill" "5835": "Wind things down" "5907": "Promote 4coder" --- name: "day267" title: "Adding Per-Element Clipping Rectangles" markers: "60": "Recap and set the stage for the day" "307": "Pig Hat Time" "314": "handmade_debug.h: Add Duration and DurationOfChildren to debug_profile_node in order to separate out the clocks" "366": "handmade_debug.cpp: Compute the DurationOfChildren and make the TopClocksList exclusive of the children" "566": ""Clocks without children"" "605": "Run the game and see a clearer picture of where our time is being spent" "707": "handmade_world_mode.cpp: Make UpdateAndRenderWorld a TIMED_FUNCTION" "762": "Run the game and see what takes the time" "870": "handmade_debug_interface.h: Make RecordDebugEvent take Name rather than DEBUG_NAME" "961": "handmade_world_mode.cpp: Insert some TIMED_BLOCKs in UpdateAndRenderWorld" "1044": "Run the game and see that GroundChunksOn takes up so much of the time" "1055": "handmade_world_mode.cpp: Nuke GroundChunksOn and consult the profiler again" "1234": "handmade_debug.cpp: Clip the profiler drawing to ProfileRect.Min.Y" "1607": "Blackboard: Picking the correct line to clip to" "1652": "handmade_debug.cpp: Make the profiler overdraw by one line" "1710": "View the profiler and see this overdrawing" "1937": "handmade_render_group.h and .cpp: Consider how to enable the bitmaps to be clipped" "2204": "Blackboard: Respecifying bitmaps" "2342": "handmade_render_group.h: Try to introduce render_entry_cliprect, to pass the clipping area down the stream" "2405": "handmade_opengl.cpp: Consider the problem with sorting" "2546": "handmade_render_group.h: Add ClipRect to render_entry_bitmap and ClipRectIndex to render_group_entry_header in order allow clipping while sorting" "2656": "handmade_opengl.cpp: Call glScissor" "2710": "handmade_platform.h: Add ClipRectCount and *ClipRects to game_render_commands" "2969": "handmade_render_group.h: Introduce game_render_clip_rect" "3141": "handmade_render_group.h: Set CurrentClipRectIndex for the entire window in Perspective" "3337": "handmade_render_group.cpp: Introduce PushClipRect" "4005": "win32_handmade.cpp: Make Win32DisplayBufferInWindow take ClipRectMemory and to call LinearizeClipRects" "4233": "handmade_render.cpp: Introduce LinearizeClipRects" "4587": "Run the game and hit an InvalidDefaultCase" "4739": "handmade_render_group.cpp: Guard against overflow in PushClipRect" "4950": "handmade_debug.cpp: Do a PushClipRect in DrawTopClocksList" "5106": "Debugger: Step into ClipRectIndex and inspect the values" "5165": "handmade_opengl.cpp: Enable GL_SCISSOR_TEST" "5195": "View our correctly clipping profiler" "5247": "handmade_opengl.cpp: Disable GL_SCISSOR_TEST in OpenGLDisplayBitmap" "5280": "handmade_render.cpp: Implement clipping in the software renderer" "5352": "Blackboard: Intersecting tiles" "5521": "View the profiler and see that it clips in both renderers" "5550": "Q&A" "5651": "What are top three reason for FPS to go down?" "5676": "Will ClipRect be used outside of debug, and where?" "5746": "Can you elaborate on the ODE you plan to replace your drag function with in MoveEntity?" "5760": "How about making the toplist scrollable? Since we now clip it, can be painful when you start profiling a lot more" "5810": "When does clipping overdrawn areas cost more than just drawing them?" "5892": "That's not entirely true, the state change on the clip isn't free, and if the size change is minor it's probably not worth it" "5951": "When you switch between the renderers, the viewing frame time is (obviously) affected. Are the clocks in our newly clipped box also affected by the renderers, i.e. ordered / distributed differently?" "5976": "build.bat: Switch to -O2 and -DHANDMADE_SLOW=0 and view the profile" "6059": "handmade_render.cpp: Ignore IGNORED_TIMED_FUNCTION and IGNORED_TIMED_BLOCK" "6305": "handmade_render.cpp: Ignore DrawRectangle and "Pixel Fill"" "6434": "What does OpenGL do when you enable gl_scissor_test? What is it testing for?" "6455": "Blackboard: glScissor" "6502": "Wrap it up" "6526": "build.bat: Switch back to -Od and -DHANDMADE_SLOW=1" "6530": "todo.txt: Update the TODO list" "6594": "Announce that the forums will be going down this weekend [note: actually the 22nd April]" --- name: "day268" title: "Consolidating Debug Links and Groups" markers: "110": "Recap and set the stage for the day" "419": "handmade_debug.cpp: Delete a load of superfluous code" "530": "4coder: Rare crash" "624": "handmade_debug.h: Rename DEBUGDrawMainMenu to DrawTrees and split it out into a recursive function called DrawTreeLink" "923": ""Sweet child of mine"" "1297": "handmade_debug.cpp: Make DrawTrees call DrawTreeLink" "1356": "View our improved profiler and consider how to proceed with it" "1763": "Debugger: Jump into DrawTrees and inspect the Tree after cloning" "2114": "handmade_debug.h: Turn debug_variable_link into a linked struct with a fake Sentinel and port everything to it" "3294": "handmade_shared.h: Make StringsAreEqual handle NULL" "3409": "View our profiler and see that cloning works again" "3419": "handmade_debug.cpp: Make CloneVariableLink just do the direct clone and return it" "3545": "Test cloning the profiler" "3599": "Q&A" "3643": "I feel I kinda lost the forecast for the trees this episode. Would you mind recapping?" "3666": "Blackboard: Linked structs" "4372": "Blackboard: Walking the tree with a recursive function" "4538": "Thoughts on linked lists, and cache friendliness? I found that a simple array, and just copying when it changes length, was way faster" "4628": "Blackboard: Cache friendliness" "4872": "Concurrency also matters. Linked lists can be better if you need multiple threads working on the list at the same time" "4908": "How do you feel about object pools as a sort of middle ground between linked lists and arrays?" "5059": "Wrap it up" --- name: "day269" title: "Cleaning Up Menu Drawing" markers: "66": "Recap and set the stage for the day" "202": "handmade_debug.cpp: Just pass the Group to the DrawTreeLink call in DrawTrees" "265": "View the Root menu in the profiler" "331": "handmade_debug.cpp: Make the FrameSlider resizable" "456": "Try resizing the FrameSlider" "555": "handmade_debug.cpp: Make the Thread view in DrawProfileBars look a little nicer" "625": "View the Thread view and note that the hover text gets clipped" "680": "handmade_debug.cpp: Make DrawProfileBars draw multiple levels of Events" "875": "View the multiple levels in the profiler" "939": "handmade_debug.cpp: Correctly Z-sort the Events" "1016": "View the correctly Z-sorted levels" "1083": "handmade_debug.cpp: Make DrawFrameBars also draw multiple levels" "1118": "View our multiple levels of Frames" "1197": "handmade_debug.cpp: Make DrawFrameBars brighten the currently viewed frame" "1406": "View the Frames view and consider improving the tooltips" "1554": "handmade_debug_ui.cpp: Introduce AddTooltip" "1934": "handmade_debug.cpp: Introduce MouseTextLayout" "2074": "handmade_debug.cpp: Make the DrawFrameSlider call AddTooltip" "2098": "View the profiler and correctly see no tooltips" "2105": "handmade_debug_ui.cpp: Make AddTooltip functional" "2448": "View the tooltip and see that it still clips" "2505": "handmade_debug.cpp: Accidentally make TextOutAt immune to the graphs' ClipRects" "2620": "View the correctly not-clipping Tooltip, but find that the Threads view is not being clipped correctly" "2729": "handmade_debug_ui.cpp: Instead make AddTooltip immune to the graphs' ClipRects" "2784": "View the profile and find that our clipping is restored to proper working order" "2827": "handmade_debug.cpp: Make the Root print out arbitrary stuff" "3487": "View our new info in the menu" "3504": "Q&A" "3547": "What is the purpose of the internal syntax?" "3604": "I loath how the compiler tells you there is a param mismatch instead of telling you a list of actual params vs the ones you typed. It could at least try to be helpful! Is this an unsolved problem in computer science?" "3656": "What were the abbreviations in the new menu header?" "3777": "People have asked before what your thoughts are on functional languages in general, but I'm curious what your thoughts are specifically on the constructs they emphasize that other languages don't, for example closures and partial application (i.e. foo taking x, y, z being called with foo x y returning a closure that takes z)" "3900": "Does the debug bitmap viewer work now when you select an entity?" "3933": "handmade_debug.cpp: Draw the bitmap on top in DEBUGDrawElement" "4009": "handmade_world_mode.cpp: Provide the ability to draw debug bitmaps using their BID" "5036": "Run the game and see that we can write to the bitmap_id reliably" "5075": "handmade_debug.cpp: Ensure the bitmap gets drawn on top" "5166": "Are we going to make a bitmap of the memory that is used / unused and when we select a unit, show where in the memory arena it is?" "5204": "handmade_debug_interface.h: Add DebugType_ArenaOccupancy" "5390": "handmade_debug.cpp: Introduce DrawArenaOccupancy" "5810": "handmade.cpp: Add a Memory DEBUG_DATA_BLOCK for the three Arenas" "6270": "handmade_debug.cpp: Provide the ability to toggle the arena occupancy graphs" "6317": "Run the game and view our new graphs" "6359": "handmade_debug.cpp: Label these occupancy graphs" "6488": ""It's all white, like Donald Trump's America"" "6497": "Run the game and view our labeled occupancy graphs" "6620": "Close down for now" "6645": "Announce that the Handmade Hero forums will be going down this weekend while Handmade Network launches" --- name: "day270" title: "Making Traversable Points" markers: "40": "Recap and set the stage for the day" "155": "Design: Room-based camera movement" "319": "handmade_world_mode.cpp, handmade_asset.cpp and handmade.cpp: Delete the ground chunks" "464": "Run the game and see exactly the same thing" "509": "Blackboard: Tile- or cell-based movement and combinatorics" "952": "handmade_sim_region.h and handmade_world_mode.cpp: Transform EntityType_Space into EntityType_Floor to respecify the world as being built up rather than carved out" "1444": "Run the game and see that the floor tiles can be picked" "1467": "handmade_world_mode.cpp: Draw the tiles" "1496": "Run the game, see our new floor tiles and consider how to use them" "1598": "handmade_world_mode.cpp: Conditionally set the Traversable flag based on the tile" "1663": "Run the game and see the traversable flag in action" "1865": "handmade_sim_region.h: Introduce sim_entity_traversable_point" "1997": "Blackboard: Snaky paths" "2095": "Consider formalising the location of entities" "2252": "handmade_sim_region.cpp and .h: Remove Gravity, ZSupported and the Traversable code in MoveEntity" "2507": "handmade_world_mode.cpp: Introduce MakeSimpleFloorCollision" "2892": "Run the game, continuously move upwards and investigate why" "3248": "handmade_world_mode.cpp: Stop making space bar trigger the jump" "3294": "Run the game and stay on the floor" "3308": "Q&A" "3406": "So how will this tile-based movement work? Will you still be able to move freely within a tile, or will the character actually "snap" to a tile?" "3426": "When will we sort out the coordinate system?" "3451": "Is it possible to get access to the source code if I lost access to my old email account?" "3533": "How about stairwells? Their traversal used to be seamless, as far as I remember. Now that the rooms are locked, how will stairwells work?" "3573": "Any plans on changing to Visual Studio Code instead of the full IDE? I believe the full debugger is included" "3613": "What are the benefits / trade-offs in having each tile be an entity?" "3764": "Are you allocating your entities on the heap or stack? Heap, right? Could you even allocate enough stuff on the stack?" "3947": "Do you foresee complications with the new grid entity floor system and the texture splats given you want a variable height per Traversable entity?" "3985": "Handle Rbnelr confusion over atomics" "4013": "So if modern CPUs usually reorder or merge writes, how do they use memory mapped registers? Can you even bit-bang a serial protocol with it?" "4170": "What is the plan with rendering when the hero walks behind a piece of terrain that is on a higher level, and obscures the hero?" "4199": "Will this system fix the collision areas getting stuck in each other if stacked, e.g. two heroes loading at the same position?" "4248": "Shut down" "4276": "Announce that the Handmade Hero forums will be going down this weekend while Handmade Network launches" --- name: "day271" title: "Hybrid Tile-based Movement" markers: "20": "Recap and set the stage for the day" "232": "handmade_sim_region.h and handmade_world_mode.cpp: Disassociate the hero's head and body" "1057": "Run the game and move the head" "1106": "handmade_world_mode.cpp: Make the body follow the head along the traversable points" "1725": "handmade_sim_region.cpp: Introduce GetSimSpaceTraversable" "1922": "Run the game and see the body following the head" "2046": "handmade.cpp: Start up directly into the game, rather than the cutscene" "2162": "Debugger: Jump into PlayWorld and investigate what's going on" "2506": ""That's just super accidental"" "2565": "handmade_world_mode.cpp: Set WorldMode in PlayWorld" "2674": "handmade.cpp: Force the start button to be pressed" "2822": "Run the game and arrive directly at the game" "2923": "win32_handmade.cpp: Correct the GameUpdateHz computation" "2999": "Run the game and move at the more correct speed" "3072": "handmade_world_mode.cpp: Make the body accelerate towards the traversable points" "3425": "Run the game and see the body accelerate towards the head" "3578": ""My body will track me, but it will never come to rest"" "3610": ""I want the head to snap back to the body when you stop pushing"" "3629": "Q&A" "3658": "When I write event-driven code, I am often forced to use dynamic memory allocation to preserve some state until it is needed by the callback. How do you deal with those situations?" "3815": "Would the Handmade debug view enable viewing structs like world mode?" "3838": "When moving diagonally, will it be clear to the player which way the body will go to get to the diagonal entity? Right now it seems kind of random" "3955": "handmade_world_mode.cpp: Introduce DesiredDirection in order to make the body move more directly to the head" "4048": "handmade_math.h: Introduce NOZ (Normalize or Zero)" "4334": "Run the game and try out our new movement" "4357": "handmade_world_mode.cpp: Conditionally set the closest point" "4443": "Run the game and see the body stopping more close to the points" "4521": "handmade_world_mode.cpp: Revert to the original movement" "4603": "This may just be an illusion but it looks like the body is snapping to the corner of tiles. Usually in tile-based games, entities occupy the center of a tile. Is this intentional?" "4642": "handmade_world_mode.cpp: Make MakeSimpleFloorCollision draw the tiles" "4681": "Run the game, see the tiles and move around on them" "4720": "At the end of Q&A, can you announce a reminder that the forums are going down shortly?" "4734": "handmade_world_mode.cpp: #if 0 that tile drawing" "4748": "Close up shop" "4805": "Announce that the Handmade Hero forums will be going down very soon while Handmade Network launches" --- name: "day272" title: "Explicit Movement Transitions" markers: "19": "Announcement: Handmade Network has launched" "347": "Recap and set the stage for the day" "770": "Blackboard: Stand and Movement as two separate modes" "865": "Blackboard: Finite State Machines" "1138": "handmade_sim_region.h and handmade_world_mode.cpp: Implement the ability to switch between two movement modes" "1407": ""Nobody cares about square root at all anymore"" "1657": "Debugger: Step into the movement code and find that we're oscillating between the modes" "1736": "Run the game and find that we stop" "1751": "Blackboard: Hopping and changing course" "2066": "Blackboard: Gravity's arc and parabolas" "2254": ""That's... math"" "2318": "handmade_world_mode.cpp: Give the hero a parabolic hop" "2643": "Blackboard: An equation to calculate the hop parabola" "3189": "handmade_world_mode.cpp: Implement this hopping equation" "3338": "Run the game and see the movement with A set to 0" "3386": "handmade_world_mode.cpp: Make the hop parabolic" "3423": "Run the game and see the parabolic hop" "3508": "A few words on the concept of reducing algorithms down to a smaller set of variables" "3547": "Q&A" "3576": "No Q&A because xanbot banned hmd_bot" "3621": "That hopping looks so cool. Can we see a little more of it?" "3683": "How did you split the head from the body?" "3694": "How interesting do you think it would be to solve for the "force" and direction required to reach a certain height on each jump? Is it just more work than it's worth for no tangible gain?" "3768": "I am guessing that both the familiar and enemies will need to move similarly to the hero. Is there much more you need to do to make this work with them?" "3786": "Can we clean up the extra head and body on screen, or are they going to be used later on?" "3828": "Why doesn't the head just head just stay on top of the body? Is that a bug?" "3891": "When writing in a procedural, I sometimes end up with deeply nested code. Should this be avoided and are there good ways to minimize this?" "3936": "This is starting to look a lot like Crypt of the Necrodancer" "3964": "Missed a lot. Are you making an engine for this game or is that stuff just there purely for you / us right now?" "4064": "Debugger: Step into RenderCommandsToBitmap and see what's happening with the Clear" "4236": "handmade_render.cpp: Set the transparency that's passed to Clear" "4274": "Run the game and see our software renderer successfully clearing" "4378": "When Z-axis is defined will up / down hopping look different?" "4397": "What are limitations of game development using C#? Do you like C# overall as a language?" "4437": "What parts of C++ are you using if you are not programming in an OOP style?" "4458": "I'm currently using a Microsoft Natural Ergonomic 4000. Thinking about replacing it with a non-ergonomic mechanical keyboard. Thoughts?" "4504": "How many A's will this game have when it's done?" "4512": "The trees on the bottom row look like they are being clipped at the top. Also C# is compiled these days to some extent" "4584": "Is that a real clicky keyboard or is it just sound effects" "4648": "Have you seen very much of apple's Swift? What are your thoughts on it now that it is open source?" "4667": "How come I have to declare a political party in order to vote in the presidential primary" "4705": "Assets: Check out the tree bitmap, and note that the reason for clipped-like looking tree assets is that they don't have the 1-pixel apron" "4872": "Wind down" "4919": "Announce the upgraded forum site on Handmade Network" --- name: "day273" title: "Animation Overview" markers: "60": "Recap and set the stage for the day" "143": "Blackboard: Animation" "282": "Blackboard: Exposure Time and Intervals of Time" "566": "Blackboard: Instantaneous Animation" "1046": "Blackboard: Doing Numerical Integration with Euler steps to compute Instantaneous Animation" "1158": "Blackboard: Lots of functions of lots of t's" "1291": "Blackboard: Physics and Animation" "1375": "Blackboard: Animation techniques: B-splines and Euler angles" "1484": "Blackboard: Orders of B-splines" "1790": "Blackboard: Parameter Spaces, State Vector and Generalized Coordinates" "2174": "Blackboard: "Position Vector" vs "State Vector"" "2284": "Blackboard: The animation pipeline: Stored -> Render Input -> Sprite List" "2387": "Blackboard: "Skeletal animation"" "2549": "Blackboard: Rendering the animation" "2643": "Internet: The Illusion of Life: Disney Animation" "2698": "Blackboard: Anticipation and Follow-through" "2853": "Blackboard: Using "map into range" to split up the animation phases" "3045": "handmade_world_mode.cpp: Add these phases to the body's hopping animation" "3200": "Run the game and look at the jump" "3220": "handmade_world_mode.cpp: Give the body some springiness" "3314": "Blackboard: Using sine to compute the curve" "3457": "Run the game and see the springiness" "3523": "handmade_world_mode.cpp: Animate the ballistic phase" "3681": "Run the game and check out the hop" "3699": "handmade_world_mode.cpp: Give the animation some follow-through on the landing" "3734": "Run the game and check out the hop" "3768": "handmade_world_mode.cpp: Speed the hop back up again and check it out" "3830": "Q&A" "3852": "handmade_world_mode.cpp: Set the Entity->FacingDirection" "3885": "What's the difference between B-splines and Bezier curves?" "3900": "Blackboard: Bezier vs B-spline curves" "3954": "Blackboard: Bezier curve" "4246": "Blackboard: B-spline curve" "4482": "From a beginner's perspective, it seems that in software rendering, keeping "milliseconds per frame" in a certain controlled boundary is somewhat in the programmer's control (depending on the code quality and orientation towards performance). Does that become more difficult when going into hardware rendering (with drivers) territory? Or is it the other way around?" "4526": "Are we going to do any compression on the image, or only movement of the torso?" "4545": "Which game design decision requires hopping / tilejumps as opposed to the previous way of moving the hero?" "4564": "Is it possible to create animations like Looney Tunes where looking at still frames you could see multiple heads and limbs or features that are extremely exaggerated and distorted? Somehow it still looks fine in motion. Smear animation is a term I could find in 30 seconds of googling" "4647": "Why not use java instead of C?" "4822": "Jmonkey and LWJGL are professional open source libraries that are written in java, just to name a couple" "4924": "Probably time to just take questions from the Handmade Network IRC?" "4976": "In order to stretch the body to the head will we implement shearing in the SE?" "4998": "What would your ideal game programming language look like?" "5016": "Have you seen this video on Ubi's Rayman 2D animation editor?" "5065": "Will the animation function eventually be moved out so other entities can use them?" "5070": "s it recommendable to mix vector and raster graphics for a game?" "5086": "David Rosen at Wolfire had a GDC talk on procedural animation. Have you seen it? If so, thoughts? [see Resources: Wolfire Blog]" "5214": "How close is humanity to programming a facsimile of our universe?" "5223": "What do you have to say about the researchers that claim that java can be faster than C++ at times?" "5313": "It's pretty great. Also, re: metaprogramming, did you see Per Vognsen's btree metaprogramming thingy? Apparently it copies Jeff Roberts' AVL-tree configurability scheme" "5327": "Runescape is a browser based MMO" "5441": "Q: Minecraft was ported to C++ I thought" "5469": "The win10 edition is C++" "5504": "Wrap it up" --- name: "day274" title: "Dynamic Animation with Springs" markers: "42": "Recap and set the stage for the day" "112": "handmade.cpp and handmade_config.h: Introduce and make Global_Timestep_Percentage editable with the debug system" "240": "Run the game reduce that Global_Timestep_Percentage" "421": "handmade_world_mode.cpp: Look at the current hopping code and consider doing physics simulation on the springiness" "605": "Blackboard: Tracking the velocity and target position of the cape" "792": "handmade_world_mode.cpp: Simulate tBob using the standard equations of motion" "972": "handmade_world_mode.cpp: Set the acceleration to 0 and see that there's no movement on that joint" "996": "handmade_world_mode.cpp: Set a loop and tweak the hopping variables" "1320": "handmade_world_mode.cpp: Restore the position to 0" "1455": "handmade_world_mode.cpp: Simulate the landing phase" "1859": "handmade_world_mode.cpp: Tune the hop" "1961": "Control the hero directly and see that the hop is oscillating" "1984": "Blackboard: Springs" "2097": "Blackboard: Undamped spring" "2248": "handmade_world_mode.cpp: Add that undamped spring equation" "2311": "Blackboard: How this spring equation works" "2405": "Blackboard: Under-, over- and critically-damped springs" "2552": "handmade_config.h and handmade_world_mode.cpp: Run at 100% global speed and slow down the head and jump" "2641": "handmade_world_mode.cpp: Tune the downward motion on the anticipation phase" "2804": "handmade_world_mode.cpp: Consider making the head snap back to the body when stationary" "2955": "Blackboard: Applying the spring technique in different directions" "3453": "handmade_world_mode.cpp: Implement this spring equation for the head" "3881": "Rerun the game and get that restorative force, but see that the facing direction is being affected by something" "4032": "Blackboard: Recentering the head along the body's axis of movement" "4079": "handmade_world_mode.cpp: Recenter the head" "4573": "handmade_world_mode.cpp: Introduce a non-normalised ddP2 in order to compute the spring" "4641": "Run the game and see that the problem is fixed" "4676": "Q&A" "4710": "The other day ingenero likened the new movement to Crypt of the Necrodancer. I like that game and see where they're coming from, but Handmade Hero already looks like it feels so much sweeter to play" "4744": "I've probably missed it, but what exactly prompted switching the hero movement from analogue-rolling to digital-tile-based-wiggle-hopping?" "4784": "Does math exist?" "4787": "Is the body always going to move on a fixed grid?" "4838": "Can we get a keyboard cam?" "4852": "Will the player be able to see the points in the design" "4873": "Is the body going to lean towards the head or is it gonna stay detached?" "4924": "Shouldn't the head always draw on top of the cape?" "5011": "Will other entities only travel on these points, too? Or can they move freely?" "5048": "Is there a name for this technique of blending canned and simulated animations? Is it a common thing allowed in animation / 3D packages?" "5176": "Why would I use an animation package instead of doing what you just did (and whatever you will do)?" "5336": "Is there any plan for eventual addition of music?" "5374": "Ham-handed Q, could you use neural networks and make something like Boston Dynamics 'BigDog'?" "5477": "Close it up" --- name: "day275" title: "Passing Rotation and Shear to the Renderer" markers: "92": "Recap and set the stage for the day" "161": "A few words on responsiveness vs aesthetics" "361": "handmade_world_mode.cpp: Introduce GetClosestTraversable to enable the HeroHead as well as the HeroBody to search for and snap to the closest point" "700": "Run the game and see the head snap" "733": "handmade_sim_region.cpp: Make the head keep facing in the direction is was going" "799": "Run the game and watch the head's facing direction" "882": "handmade_world_mode.cpp: Disable the sword in favour of implementating strafe hop" "943": "Run the game and try out the strafing" "995": "handmade_world_mode.cpp: Make the head not recentre" "1039": "Run the game and try the movement" "1056": "handmade_world_mode.cpp: Use a weaker spring to recentre the head" "1112": "Run the game and try out the recentering" "1143": "handmade_world_mode.cpp: Make the head not recentre" "1189": "Run the game and try out the movement" "1387": "handmade_render_group.h: Add XAxis and YAxis to render_entry_bitmap" "1519": "handmade_opengl.cpp: Make OpenGLRenderCommands work with render_entry_bitmap" "1636": "Blackboard: Handling parallelograms" "1749": "handmade_opengl.cpp: Calculate the four points" "1971": "handmade_render.cpp and handmade_render_group.cpp: Make DrawRectangleQuickly and PushBitmap work with render_entry_bitmap" "2069": "Run the game and see that everything is messed up" "2101": "handmade_open.cpp: Correct the point calculation" "2116": "Blackboard: How we are calculating the points" "2155": "Run the game and see that we're good" "2166": "handmade_render_group.cpp: Consider how best to specify the axes" "2512": "Blackboard: Rotating the body's YAxis to point to the head" "2825": "handmade_render_group.cpp: Make PushBitmap and GetBitmapDim take XAxis and YAxis" "3057": "handmade_world_mode.cpp: Make the body's YAxis point towards the head" "3531": "Run the game and admire the stretching" "3582": "Q&A" "3619": "Zircon encrusted tweezers? Are you moving to Montana soon?" "3633": "Why does our limbless hero need suffer in such gruesome ways" "3659": "Do I need the payed version of Mischief to change the background color?" "3689": "Will you try rotation to visually compare against shearing before deciding?" "3746": "You wrote the scale / shear this way because it's already done in the software renderer but these transformations would usually be done in a vertex shader, right?" "3832": "Some other games have done similar move styles, but they use a floating indicator instead of separating the head from the body. Your thoughts?" "3846": "For collision detection will there be skewed boxes as well or will it just be AABB?" "3875": "So we move tile to tile? Haven't seen the new movement" "3886": "Are we eventually going to move these over to shaders?" "3983": "Any word on the new debugger?" "4029": "You had a stream about someone contacting you about making a debugger" "4130": "I doubt the concept of shaders is going anywhere soon" "4377": "Do you think you'll use the spring code from the other day on the camera movement? I'm imagining a critically damped spring would be the thing to use for that" "4526": "For camera stuff I just do x += (x - dest) / 10 or something like that. What would that be?" "4580": "That's not accounting for t, that's if it was instantaneous" "4648": "Should be (dest - x) I'm assuming" "4662": "I used to do like fixed FPS, so it was fine, but I've changed. Hold on I'll look it up" "4684": "Blackboard: GarlandoBloom's camera movement" "4866": "Plans on adding camera shake or blur or similar if the hero gets hit or a bolder hits the ground near the hero?" "4924": "Wrap it up" --- name: "day276" title: "Tuning the Body Animation" markers: "77": "Run the game, demo our problem with the stretching not looking great and consider moving to a more top-down perspective" "192": "Blackboard: How top-down art may solve the detachment problem" "315": "Run the game and demo the lack of collision on the side walls" "450": "handmade_world_mode.cpp: Move the head down and draw it in front of the cape" "509": "Blackboard: How the art assets are currently packed" "613": "handmade_render_group.cpp: Investigate the sorting" "717": "Debugger: Break on PushBitmap for the cape and head and inspect their SortKey" "963": "handmade_world_mode.cpp: Sort the body parts slightly more correctly" "1182": "handmade_world_mode.cpp: Limit the shearing" "1454": "handmade_world_mode.cpp: Mitigate the separation problem" "1953": "Run the game and consider disallowing diagonal movement" "2069": "handmade_world_mode.cpp: Disallow diagonal movement" "2341": "Run the game and try out the cardinal movement" "2534": "handmade_world_mode.cpp: Clean up the controller code" "2749": "Run the game and try out the controller code" "2781": "handmade_world_mode.cpp: Re-enable the head's recentering code" "2804": "Run the game and try out the recentering" "2852": "handmade_world_mode.cpp: Delay the recentering" "2995": "handmade_math.h: Introduce ClampAboveZero" "3161": "Run the game and try out the delayed recentering" "3307": "Q&A" "3331": "Do you think like a sort of rhythmic based movement where the hero would have to wait a bit before being able to move again (say he's getting ready for a jump instead of stamina-lessly jumping around non-stop) could perhaps help in this situation? Realise it's a design decision and might not be what you're looking for, but perhaps you haven't entertained the idea" "3381": "Do you think rotating the torso would help?" "3432": "For the Q&A can you have the hero walk around on a live loop?" "3464": "Try wrapping the body around bezier rather than just linear stretching?" "3504": "For the up-down motion, couldn't you forgo the stretch, and have a jump of each part?" "3518": "Why wouldn't you shear the top of the feet to stay under the moving body?" "3551": "What about a small translation of the body before and after the jump, say 10%-20% of the distance between adjacent dots?" "3592": "handmade_world_mode.cpp: Displace the body based on the distance of the head from the nearest traversable point" "3906": "Run the game and check out the displacement" "3935": "handmade_world_mode.cpp: Apply the floor displacement only to the cape" "3956": "Run the game and check out the cape's displacement" "3995": "The more I see the more I like this. I wonder whether a subtle head bob may add a feeling of believability. Just a thought" "4067": "Would it help if the body stayed on the tile, but the cape was positioned between the body and the head?" "4101": "Consider asking Yangtian for art that is more top-down" "4188": "Perhaps a minimum stretch length so you don't get disappearing bitmaps while moving down?" "4203": "Close up" "4241": "Announcement: HandmadeCon 2016" --- name: "day277" title: "The Sparse Entity System" markers: "14": "Introduce Milton" "85": ""I have no idea how to say Sergio properly, let alone sexily"" "382": "Recap and set the stage for the day" "627": "Blackboard: Entity systems" "887": "Blackboard: Current compositional approach" "1020": "Blackboard: Looking Glass's Act / React Model" "1288": "Blackboard: Problems with the AOS approach" "1485": "Blackboard: Sparse Entity System" "1626": "Blackboard: Inheritance" "2204": "Blackboard: When inheritance falls apart" "2425": "Blackboard: "Inheritance is compression"" "2807": "Blackboard: One epically huge entity struct" "3084": "Blackboard: Sparse matrix solver" "3157": "Blackboard: Summary of the plan" "3277": "Q&A" "3336": "Can you talk about the dynamic dispatch?" "3369": "Blackboard: Dispatch" "3653": "Blackboard: C++'s implementation of dynamic dispatch" "4050": "Blackboard: Why our system won't use dynamic dispatch" "4192": "Do you use the struct entry method in your current game?" "4222": "Have you seen my psuedo-hacked discriminated union inheritance system that I use in my game on stream? It's pretty cool" "4252": "What made you choose this approach over an AoS style + storing indices of each separate component in the main entity struct?" "4287": "I missed it. What about the matrix [i,j]? I was confused there" "4344": "How and where would you go about checking if a property existed on your 'mega-struct' whenever you want to do your operations? Would they all be null pointers if undefined?" "4395": "What are you going to use to track which struct members have been touched / set back to null?" "4453": "What portions of this design could you foresee causing perf issues?" "4742": "What are some alternatives to an entity system?" "4861": "Are you already thinking of a backup plan for the entities and how you would transition to that system if you had to?" "4947": "Do you play Street Fighter? Who is your favorite character?" "5034": "Will the entity system include things such as particle effects?" "5073": "Did you play Bomberman?" "5077": "You can't stand the Street Fighter pause but you liked the Mortal Kombat rotoscope?" "5127": "Yeah that seems reasonable, it does seem unlikely that you'd get 300 entities needing 60FPS simulation except, as you say, bullet hell with bullets-as-entities rather than being their own optimized thing" "5257": "Close down" --- name: "day278" title: "Moving Entity Storage into World Chunks" markers: "89": "Recap and set the stage for the day" "314": "Blackboard: How the simulation region streams in entities as you traverse the world" "572": "Blackboard: Entities referencing each other" "749": "handmade_world.h: Add a read / writeable EntityData and EntityDataSize to world_entity_block" "892": "Debugger: Compile and run and hit an assertion in PushSize_" "1011": "handmade_world.h: Change ChunkHash in world to be a pointer and add the Chunks as a singly-linked list" "1326": "handmade_world.cpp: Introduce ClearWorldEntityBlock" "1445": "handmade_world.cpp: Clean up CreateWorld" "1475": "Run the game and see what happens" "1489": "handmade_sim_region.cpp and handmade_world_mode.cpp: Excise the sword" "1586": "Run the game and find that we're still running okay" "1595": "handmade_world_mode.h: Remove the LowEntities from game_world_mode" "1745": "handmade_sim_region.cpp: Rewrite LoadEntityReference so that an entity can only been accessed if it is within your simulation region" "1846": "handmade_sim_region.cpp: Make BeginSim store the actual entities instead of indices" "2154": "handmade_sim_region.cpp: Disable some of EndSim for now just to see what breaks" "2226": "handmade_world_mode.cpp: Introduce BeginLowEntity and EndLowEntity and split AddLowEntity out into these functions in order to create a low entity and then pack it into its actual position location" "2863": "handmade_world_mode.cpp: Introduce PackEntityIntoChunk to be called in EndLowEntity" "2957": "handmade_sim_region.cpp and handmade_world_mode.cpp: Work through a plethora of compile errors to use entity_id" "3889": "Q&A" "3949": "This is more of a meta-question but I found myself placing TODOs in my code at places that I don't want to deal with while I work on something else. However, as we all procrastinate, how come back to the TODOs?" "4013": "What's the highest number of errors you've ever had after compiling?" "4029": "I arrived too late to the prestream to let you know that yesterday's episode hasn't yet made its way to YouTube" "4050": "Wrap it up" --- name: "day279" title: "Finishing World Chunk Entity Storage" markers: "52": "Blackboard: Why make an entity system using a SOA (Struct of Arrays) rather than an AOS (Array of Structs)" "293": "Recap and set the stage for the day" "590": "Explain the problem with pulling the world_entity_blocks out of the ChunkHash" "672": "Blackboard: Transactional Memory" "964": "Blackboard: Making the entity system multithreaded" "1163": "handmade_sim_region.cpp: Make BeginSim remove the Chunks and Blocks, and return them to the free list" "1355": "handmade_sim_region.cpp: Make EndSim pack the entities into a new chunk" "1832": "handmade_world.cpp: Delete ChangeEntityLocation and clean up compile errors" "2067": "Anticipate 4coder's code intelligence" "2152": "handmade_world_mode.cpp: Replace low_entity with entity" "2192": "handmade_sim_region.h: Replace sim_entity with entity" "2462": "handmade_world.cpp: Remove ChangeEntityLocationRaw and introduce PackEntityIntoWorld" "2925": "handmade_world.cpp: Introduce PackEntityIntoChunk" "3049": "handmade_world.h: Make FirstBlock be a pointer in world_chunk" "3202": "handmade_world.cpp: Introduce HasRoomFor" "3423": "handmade_world.cpp: Introduce AddBlockToFreeList and AddChunkToFreeList" "3585": "handmade_world.cpp: Introduce RemoveWorldChunk" "3661": "handmade_world.cpp: Split GetWorldChunk out to GetWorldChunkInternal in order to provide multiple entry points" "4063": "Run the game and let it crash and burn" "4093": "handmade_world_mode.h: Support creating multiple entities at the same time" "4309": "Q&A" "4367": "Blackboard: Using a Pointer to a Pointer to enable editing of chunks" "4577": "How are you finding Milton? I didn't catch the start of the stream sorry" "4658": "How do you pronounce your name?" "4690": "Is the Sparse Entity System the same as "mixins" that you mentioned before? If not, are we ever going to use or talk about mixins? I'm really curious as to what they are" "4708": "Blackboard: Mixin" "4785": "Do friend classes count as mixins?" "4832": "Couldn't you avoid having to compress the entities if you used some unions in the entity?" "4879": "How are you finding 4coder so far? Any features you find missing? Is it worth getting into coming from emacs?" "4955": "What do you think of the other more data-oriented entity system implementations online (like anax, EntityX, etc.)?" "5035": "Wrap it up" --- name: "day280" title: "Cleaned Up Streaming Entity Simulation" markers: "50": "Recap and set the stage for the day" "71": "handmade_world.cpp: Get the sizeof *Source in PackEntityIntoChunk" "135": "handmade_sim_region.h: Rename StorageIndex to ID in entity" "252": "handmade_sim_region.cpp: Rename GetHashFromStorage to GetHashFromID" "295": "handmade_sim_region.h and .cpp: Remove EntityFlag_Nonspacial from entity_flags and continue cleaning stuff up" "486": "handmade_world_mode.cpp and handmade_entity.h: Remove the Sword" "754": "handmade_world.cpp: Make PackEntityIntoWorld store the entity's location" "940": "Debugger: Step into BeginSim and find that we don't get any entities out in our initial pack" "1101": "Debugger: Step into PackEntityIntoWorld and follow the code through to RemoveWorldChunk" "1437": "handmade_world.cpp: Increment the Chunk->EntityCount in PackEntityIntoChunk" "1503": "Run the game and see that we're getting closer, but that the body has stopped tracking the head" "1666": "handmade_sim_region.cpp: Collapse down AddEntityRaw and AddEntity" "1934": "Run the game and see exactly the same thing" "1941": "handmade_sim_region.cpp: Introduce ConnectEntityPointers" "2095": "Run the game and find that the head and body remain connected" "2117": "handmade_entity.h: Move the entity-related structs in from handmade_sim_region.h" "2313": "handmade_world_mode.cpp: Disable the Z-movement and then try traversing the world" "2388": "handmade_sim_region.cpp: Introduce DeleteEntity" "2606": "Run the game and test entering and exiting it" "2713": "handmade_entity.h: Explain why world_position is no longer necessary and consider removing it" "2887": "handmade_sim_region.cpp: Make BeginSim compute world_position and pass ChunkDelta to AddEntity" "3079": "handmade_sim_region.cpp: Make the EntityP in EndSim relative to ChunkP" "3402": "Run the game and find that we can go off the screen okay" "3418": "handmade_sim_region.cpp: Set the Entity->P and chunk movements at the end of EndSim" "3468": "Run the game and find that the camera does now follow the hero" "3522": "Q&A" "3625": "Is there any real difference between #ifndef and #if !defined? I always use the first but I see you use the latter" "3655": "Do you feel like we take steps backward when we get into code we haven't been in in a while, e.g. the problems with moving the screen?" "3682": "Do you use a lot of header files?" "3713": "Remove all instances of #if !defined" "3967": "Why not #pragma once?" "4136": "Would you say the architecture of the entity system is based more on experience than on exploration?" "4168": "Do you have a plan for the "components" of the entities? Just use the flags like you are now?" "4187": "As a codebase grows new functions are created and others are no longer called anywhere. Are there any good ways that you recommend for finding out which functions / blocks of code are never used anywhere?" "4289": "Is there a way to run the game "entirely" and find out what parts of your code aren't being used, to get rid of?" "4382": "The dynamite jack entity system is similar (but without compression)" "4417": "Have you checked LOC recently?" "4454": "How is your arm now? Any chance of a streamathon?" "4479": "CTime needs cloc built-in" "4537": "Re code coverage, when Farbrausch was trying to cut down size of Kkrieger they wrote a quick code coverage tool called Lekktor and because someone didn't use a certain key in the menu, the code to handle it was left out in the released version" "4833": "Wrap it up" --- name: "day281" title: "Animating the Camera Between Rooms" markers: "88": "Recap and set the stage for the day" "204": "handmade_sim_region.cpp: Investigate the glitch in the room-based camera movement" "383": "Blackboard: How the camera was being moved" "447": "handmade_sim_region.cpp: Correct the displacement and run the game" "674": "Blackboard: Camera control, hysteresis and perception grammar" "1205": "Blackboard: Hysteresis" "1538": "Blackboard: What we need hysteresis for in Handmade Hero" "1818": "handmade_world_mode.h: Add CameraOffset to game_world_mode in order to decouple the camera and the simulation region" "2012": "handmade_world_mode.cpp: Test offsetting the camera" "2299": "handmade_sim_region.cpp: Introduce RoomDelta and hRoomDelta to make it easier to tweak values" "2429": "Run the game and try moving between rooms" "2431": "handmade_sim_region.cpp: Displace the camera away from the hero" "2474": "handmade_sim_region.cpp: Scroll the camera halfway into the apron" "2824": "Run the game and see the camera's half-interpolation" "2842": "handmade_sim_region.cpp: Scroll the second half of the transition" "2898": "Run the game and see the full scroll in action" "3033": "handmade_sim_region.cpp: Tune the camera control" "3262": "Blackboard: Parabolic arc equation" "3564": "handmade_sim_region.cpp: Give the camera this parabolic arc" "3592": "Run the game and enjoy the camera movement" "3708": "handmade_sim_region.cpp: Update the Entity->P before computing the CameraOffset" "3835": "Run the game and see that the glitch is gone" "3845": "Q&A" "3900": "Are you concerned about the player seeing outside the boundaries of the map or seeing into other rooms when the camera zooms out?" "3922": "So, no more smooth scrolling?" "3947": "I know the rooms are going to fit the screen, but will there be variable sized rooms with the camera making it fit to the screen?" "4009": "When thinking of enemies, would you have classifications for AI, e.g. Level 1 approach constantly (zombie)? What would be the main levels you'd say for difficulty or reward feeling?" "4024": "gasto5 When does he turn 39?" "4039": "Have you seen the warp glitch from Link's Awakening? How would you avoid that?" "4169": "You press start when before you enter a room and the link will end up on top of the screen" "4227": "Blackboard: Our coherent sense of world space vs What may be happening in Link's Awakening" "4387": "If you want a good hysteresis example a heater controller does the job" "4453": "We are done" --- name: "day282" title: "Z Movement and Camera Motion" markers: "160": "Run the game and show where we're at" "349": "handmade_world_mode.cpp: Randomise the heights of the traversable points" "585": "Run the game and traverse the room" "813": "handmade_sim_region.cpp: Provide the ability to interpolate the camera's height" "1052": "4coder: Spot a potential bug with a space being inserted after a square-bracket" "1173": "handmade_sim_region.cpp: Make AddStandardRoom form a ramp" "1258": "Run the game and attempt to hop up the ramp" "1404": "handmade_world_mode.cpp: Set HeadToPoint.z to 0" "1430": "Run the game and find that we can now hop upwards" "1508": "handmade_world_mode.cpp: Make AddStandardRoom produce a shallower ramp" "1539": "Run the game and traverse the shallower ramp" "1592": "handmade_world_mode.cpp: Comment out the HeadToPoint.z setting and again traverse the shallower ramp" "1706": "handmade_world_mode.cpp: Compute the HeadToPoint in order to prefer traversable points in the XY plane" "1860": "Run the game and traverse the world" "1998": "Blackboard: The Plan for Final Z" "2237": "handmade_world_mode.cpp: Let the ramp go below 0 and traverse it in an effort to see the alpha-fade" "2349": "handmade_world_mode.cpp: Investigate why the alpha-fade is not happening" "2467": "Debugger: Break on CameraRelativeGroupP initialisation and inspect the values" "2614": "handmade_world_mode.cpp: Only create one room" "2781": "handmade_world_mode.cpp: Add a DEBUG_VALUE for CameraRelativeGroundP to the HeroHead" "2810": "Run the game, traverse the ramp and watch that CameraRelativeGroundP" "2869": "handmade_world_mode.cpp: Add that DEBUG_VALUE to the Monstar" "2903": "Run the game and note that we don't load in the world one layer above us" "2948": "handmade_world_mode.cpp: Add fifteen floors to the SimBoundsExpansion" "2983": "Run the game and find that the alpha-fade is working" "3022": "handmade_world_mode.cpp: Add another column of trees to the room" "3103": "Run the game, trigger the fade and explain the problem with alpha blending multiple faded entities" "3304": "handmade_render_group.h: Consider ways to blend the alpha" "3504": "Q&A" "3544": "That up / down camera movement looks so cool. I do hope the terrain height of the rooms makes good use of this" "3582": "Could you do something with GL_MIN / GL_MAX blend equation for the alpha?" "3792": "Can you create the word of warcraft game?" "3859": "If the contour of your entities wasn't antialiased, you could have used the depth buffer and reverse the render order for the entities being faded (front to back), but alas, it is hard to do properly with the alpha blending around the contours" "3950": "You mentioned rendering to an offscreen buffer then compositing as one means of getting the desired alpha effect, but you also mentioned something along the lines of using a "fragment list"? could you please elaborate a bit more on that approach?" "3983": "Blackboard: Per-fragment atomic lists" "4688": "That sounds insane. Are there any modern games that use this?" "4732": "Could you just pre-render normally to an offscreen buffer, and then composite it with the primary frame buffer with the fade-out alpha?" "4762": "If the antialiasing didn't throw a wrench, you could have used the depth-buffer-front-to-back rendering method all the way, and compensate for some of the extra bandwidth on less overdraw" "4836": "I mean that sounds like it has huge performance implications" "5039": "Speaking of your smoke example, did you see what David Rosen posted today?" "5098": "I thought most games were only designed to max out console hardware?" "5155": "Wrap it up" --- name: "day283" title: "Making Standing-on a More Rigorous Concept" markers: "246": "Do you have any favorite insects?" "271": "Good evening, Casey! Had a bit of an "uh-oh" moment today while annotating as you went to the episode guide to double-check what Day it was, but the expected previous day was not there..." "378": "If there are multiple GL contexts in use at the same time, and both have workloads simultaneously, how does the GPU / GPU driver decide to schedule those workloads? I noticed that windows seems to prioritize the active window's OpenGL context if you happen to have multiple OpenGL apps open at the same time (i.e. the active window will perform much better), so that's kind of interesting..." "501": "What are your thoughts on flowchart-based programming, and do you think they are effective in game programming?" "544": "What's your opinion on the Vulcan API?" "562": "I'm thinking more along the lines of what UE4 implements in the form of blueprint" "681": "What do you think about structured editors?" "732": "I think that the main use case of boxes-and-arrows-type programming is to convince non-programmers that they're not programming" "750": "Where are we on the Handmade Hero todo? Seems like a long time since we last updated it" "789": "Stream Begins Now" "886": "Run the game and set the stage for the day" "1123": "Blackboard: Atomic Hop and Floating position" "1467": ""I forgot there's a me down there"" "1818": "Blackboard: The problem with merry-go-rounds and potential decapitation" "2354": "handmade_entity.h: Introduce traversable_reference and add two of those to entity" "2567": "handmade_sim_region.cpp: Introduce LoadTraversableReference and StoreTraversableReference" "2727": "handmade_sim_region.cpp: Move GetClosestTraversable in from handmade_world_mode.cpp and make it record the Index" "3268": "handmade_entity.h: Make entity track the traversable that we're on" "3409": "handmade_world_mode.cpp: Make AddPlayer take a traversable_reference and create players on the closest traversable" "3465": ""I don't want them to start invalid"" "3720": "Run the game to see what we have wrought, and hit the Assert in GetSimSpaceTraversable" "3878": "Debugger: Hit that Assert and find that Head->StandingOn is NULL" "4036": "handmade_world.cpp: Do all of the edits in PackEntityIntoChunk" "4203": "Run the game and successfully hop around" "4215": "handmade_world_mode.cpp: Make the HeroBody recover its position, and introduce AddFloatyThing" "4468": "handmade_world_mode.cpp: Make the FloatyThingForNow move up and down" "4554": "Run the game and try standing on the FloatyThingForNow" "4610": "handmade_world_mode.cpp: Make AddStandardRoom add only the FloatyThingForNow at its location" "4686": "Run the game and try again to stand on the FloatyThingForNow" "4775": "Q&A" "4822": "This sounds like a job for hysteresis, if I understand it right" "4864": "They implemented a structured editor for greenfoot" "4901": "So, we are planning to have the head detached forever?" "4929": "Where are the gloves? You will program in custom glove movement, right?" "4947": "Any idea when you plan on adding in the correct-perspective art so that the hero looks less strange?" "4971": "So in theory you could test this by adding a second hero with the xbox controller and making sure they don't stand on the same tile?" "5004": "Close this down" --- name: "day284" title: "Reorganizing the Head and Body Code" markers: "100": "Run the game and recap our current situation" "176": "Stand on the FloatyThingForNow and note a bug" "224": "handmade_world_mode.cpp: Set Found = false for the HeroBody" "318": "Run the game, note that the body cannot find a traversable and consider making the head operate more specifically" "466": "handmade_world_mode.cpp: Decouple of the hopping from the head and make it happen more predictably" "747": "Run the game, move the head and find that the body does not hop" "777": "4coder: Indentation request" "792": "handmade_world_mode.cpp: Make the controller also control the body, if one exists" "1297": "Run the game and hop around" "1308": "handmade_world_mode.cpp: Make the Head test to see if the Body can move to a traversable" "1568": "handmade_entity.h: Introduce IsEqual" "1701": "Run the game and find that nothing has changed" "1851": "handmade_world_mode.cpp: Investigate this behaviour with the FloatyThingForNow like a bug, starting with DEBUG_VALUE" "2127": "Record a loop in order to investigate it" "2760": "Blackboard: Figuring out the tile delta" "3576": "win32_handmade.cpp: Copy a loop and provide the ability to play one back independently of recording" "3712": "Run the game and try playing back a loop" "4994": "Moment of realisation: This isn't even a bug" "5084": "Owl of Shame Moment: FloatyThingForNow is hard-setting the P.z" "5105": "Blackboard: How the FloatyThingForNow messes with the relative coordinate system" "5240": "handmade_world_mode.cpp: Set the P.z as a delta for now and then hop onto the FloatyThingForNow and find that the bug has gone" "5319": "Blackboard: sine and cosine as derivatives of each other" "5706": "Q&A" "5766": "Is there a geometric explanation for the quaternion sandwich product? Where does the formula q * p * conj(q) come from?" "5820": "I am a bit unclear on why the relative positioning of Z worked. Is Z rebased somewhere in the code?" "5913": "I'm still quite newbie on programming, but wouldn't commenting your code a bit more help in situations like today?" "6040": "Only three swears? I have counted a lot more than that" "6064": "So, not only did that bug effect the floating thing going to high / low, but it also was the cause of the head picking the wrong point and the body jumping to it?" "6083": "Blackboard: What was causing the guy to jump" "6195": "What if you really wanted to set an absolute position for an entity? How would you handle that?" "6240": "Blackboard: Quaternion Sandwich Product or Similarity Transform" "6356": "Yes, that's the question" "6394": "Blackboard: The algebraic reason" "6536": "Blackboard: Things that represent a frame of reference" "6878": "Blackboard: Knowing what B is in the space of A" "7047": "Blackboard: The Similarity Transform" "7396": "Blackboard: Diagram of the transform" "7637": "Blackboard: Why do we care about this?" "7835": "Blackboard: Thinking about this algebraically" "7925": "Blackboard: Doing this transform, with P encoded in a different space" "8168": "Blackboard: Transforming a bone chain" "8462": "Blackboard: Inserting and expanding the identity" "8743": "Thank you, very insightful explanation. Can you recommend a book where I can learn more about these kinds of things? How did you learn it all in such an intuitive way?" "8961": "Would any of this have been mentioned in the comments in the Granny source code, or is it considered "obvious" to people working in that context?" "9051": "Wrap it up" "9092": "Relaunch the awesome Milton and find that everything is saved and undoable" --- name: "day285" title: "Transactional Occupation of Traversables" markers: "95": "4coder: New version 4.0.5, with indentation and scrollbars" "205": "Recap and set the stage for the day" "276": "handmade_world_mode.cpp: Disable the slope" "374": "4coder: Bug with editing in the left-hand pane" "449": "handmade_entity.h: Add an entity *StandingOn to entity_traversable_point" "571": "handmade_sim_region.cpp: Make LoadTraversableReference write to the entity's collision volume if they have a pointer set" "657": "handmade_world_mode.cpp: Colour the traversable if it has an Occupier" "703": "4coder: Swoon over the cool new indentation" "763": "Run the game and find that the traversables already have the new colour" "975": "handmade_entity.h: Make the Traversable a property of the entity" "1193": "Run the game and pacman up the traversable points" "1257": "4coder: Realise that we're now editing in the left-hand pane" "1281": "handmade_world_mode.cpp: Check if a traversable is available before hopping to it" "1394": "handmade_sim_region.cpp: Introduce TransactionalOccupy and GetTraversable" "1889": "Run the game and note a couple of problems" "2066": "Blackboard: Transitioning from Standing On to Moving To" "2238": "handmade_entity.h and handmade_world_mode.cpp: Assume that a 1-square-sized entity occupies only one square at once" "2329": "4coder: Outdated jump-to-error" "2585": "Run the game and find that the colouring of the traverables is working as expected" "2625": "handmade_world_mode.cpp: Reimplement the ability to add new heroes" "2713": "Run the game, try adding new heroes and enjoy the weirdness" "2824": "handmade_world_mode.cpp: Consider making AddPlayer more robust" "3211": "handmade_world_mode.cpp: Set HeroesExist in both cases, run the game and consider keeping AddPlayer as it is" "3281": "Q&A" "3322": "This debug world just gets progressively weirder every day" "3394": "Why don't the cloned players jump to points when their head moves over them?" "3441": "handmade_world_mode.cpp: Make the hopping happen whether or not a controller is controlling the hero" "3586": "Run the game and spawn a ton of heroes" "3612": "handmade_world_mode.cpp: Keep those heroes hopping" "3654": "Run the game and watch them hop" "3696": "handmade_sim_region.cpp: Introduce traversable_search_flag and add Unoccupied flag to GetClosestTraversable" "3741": "4coder: Praise Allen for the alignment" "3793": "4coder: Bogus indentation" "3861": "Run the game and spawn a line of heroes" "3914": "handmade_world_mode.cpp: Made AddPlayer take SimRegion in order to do GetClosestTraversable" "4046": "Run the game and find that we're still not quite right" "4100": "handmade.h: Add DebugSpawn to controlled_hero in order to test this adding" "4342": "handmade_sim_region.cpp: Make GetSimSpaceTraversable copy the Occupier" "4386": "Run the game and spawn some correctly positioned heroes" "4410": "handmade_world_mode.cpp: Make DebugSpawn not override us" "4434": "Run the game and just add new people" "4565": "Wind up" "4568": "4coder: Recap the one weirdness with the if [see 1:03:13]" --- name: "day286" title: "Starting to Decouple Entity Behavior" markers: "65": "Recap and set the stage for the day" "388": "handmade_entity.h: Consider how to eliminate Type from the entity struct" "690": "handmade_entity.h: Move things off the Type variable that need not be there" "964": "Run the game and see that we've lost nothing, besides the FloatyThingForNow" "1211": "handmade_entity.h: Partition the entity struct to separate the meaningful from the exploratory" "1274": "handmade_entity.h: Add an entity_reference *PairedEntities and a u32 PairedEntityCount in the meaningful area to provide some notion of pairing of entities" "1615": "Blackboard: Norm, and Pythagoras' Theorem" "1951": "handmade_world_mode.cpp: Write the usage code for pairing multiple entities" "2202": "handmade_world_mode.cpp: Consider making PackEntityIntoChunk pair aware and PairedEntities dynamically resize, and how to track the entity_id" "2829": "handmade_entity.h: Consider introducing enum entity_relationship to denote how an entity is paired" "3108": "handmade_entity.h: Introduce ReferenceIsValid, entity_stored_reference and ReferencesAreEqual" "3401": "handmade_world_mode.cpp: Make PackEntityReferenceArray correctly pack these variably-sized paired entities" "3819": "handmade_world.cpp, handmade_sim_region.cpp and handmade_world_mode.cpp: Fix compile errors" "4077": "Q&A" "4107": "A fairly simple way to describe or understand the infinity norm is to draw the unit hyperspheres for each of those common norms. The 1-norm would be a diamond shape, 2-norm is the regular circle / hypersphere, 3-norm gets more squareish / hypercubish and so on. You'd quickly see that this series converges towards a square / hypercube" "4142": "Have you seen Scott Meyer's talk on CPU caches? He talks about how it's better to store data of the same type together in memory because they end up on the same cache line, which is good for performance. Is this something that you think about, or will cover in Handmade Hero?" "4282": "Could you use the entity pairing concept for a vehicle-occupant relationship, like an airship and its passenger(s)? And, if so, (how) would movement work on it?" "4304": "I was just wondering why you don't have a subscriber button for those that enjoy your frequent broadcasts. From what I gather you were offered partnership but turned it down due to something in the contract. Can you tell me a little why you made that decision and what options do you have to donate?" "4510": "Is it not possible to subscribe to forum posts anymore now since the new stuff was made I don't get any posts to my mail" "4557": "Subscribe doesn't make it ad-free anymore, as far as I know" "4709": "This entity reference stuff feels premature to me since I don't think we have a lot of examples of how it will be used. Are you doing it now for a particular reason?" "4885": "Close down" --- name: "day287" title: "Adding Brains" markers: "56": "Blackboard: Dynamically controlling snake-like multi-segment entities" "415": "Blackboard: Controller templates" "882": "4coder: Reproduce the pane creation bug" "1023": "handmade_entity.h: Remove entity_relationship and ReferenceIsValid and, from entity, PairedEntityCount and PairedEntities" "1094": "handmade_entity.h: Introduce entity_controller_type, entity_controller_slot and entity_controller_id, and add one of each to entity" "1337": "handmade_entity.h: Consider how this system will replace entity_type" "1499": "handmade_entity.h: Rename entity_controller_* to brain_*" "1544": "handmade_sim_region.h: Introduce brain_hash and add an array of them to sim_region" "1830": "handmade_world.cpp: Rename PackEntityReferenceArray to PackEntityReference and make it work on only one entity" "2218": "handmade_world.cpp: Make PackTraversableReference and PackEntityIntoChunk take a sim_region" "2269": "handmade_entity.h: Introduce IsDeleted" "2335": "handmade_sim_region.cpp: Move some functionality from LoadEntityReference to GetEntityByID and make it call the latter" "2432": "handmade_sim_region.cpp: Make PackEntityIntoWorld take a sim_region" "2505": "handmade_world_mode.cpp: Remove BodyRefs and HeadRefs from AddPlayer, and initialise a brain_id and some brain data for the Body and Head" "2648": "handmade_world_mode.cpp: Introduce AddBrain" "2806": "handmade_sim_region.h: Add MaxBrainCount, BrainCount and *Brains to sim_region" "2820": "handmade_world_mode.cpp: Excitedly make UpdateAndRenderWorld loop through the brains and do the brain logic" "2941": "handmade_sim_region.h: Add a brain_type to brain" "2962": "handmade_world_mode.cpp: #if 0 out the PairedEntities code for now" "3046": "Run the game with our disabled controllers" "3079": "handmade_world_mode.cpp: Loft the hero head controller code up into Brain_Hero and begin writing the brain logic" "3194": "4coder: Bright white bug" "3312": "handmade_sim_region.h: Add a brain_id to brain" "3370": "handmade.h: Change entity_id to brain_id in controlled_hero" "3425": "handmade_world_mode.cpp: Fix compile errors" "3667": "handmade_world_mode.cpp: Make AddPlayer return a brain_id" "3722": "Q&A" "3856": "I must have missed the bit about the snake. What is that?" "3947": "It's actually a millipede" "3970": "How long do you hope this will go on for? Do you see yourself doing different game once this is finished?" "4043": "You mentioned you'd spend four hours cleaning code. Why not have a Handmade Hero day once every other month or so and deal with problems like that?" "4063": "About the one entity per grid spot checking, how will you handle leaving a spot just before a monster lands there? Right now it's binary. Do you plan to add a fuzziness as you step off a square onto another one and a monster lands on your spot?" "4193": "Someday I will have to ask you about how to think when representing data in a program. I understand structs, enums, arrays and such. But what regulates when to use which?" "4446": "So the idea is to have the entity system both be able to support groups of entities that change from one into another (like a monster that mimics other objects), and entities that when separated from the group can take action on their own (like a necromancer resurrecting a ripped off arm)?" "4545": "Slightly off-topic: On average how many hours a day do you work on 1935?" "4588": "On the note of UML, how much / often would you say you deal with that at work, if at all? In the gamedev industry, anyway" "4602": "Good answer, I understand what you mean. Just do it enough and you'll see what works. Experience. Thanks!" "4610": "Have you thought about using Vulkan? It is super low-level access to hardware" "4631": "Wrap it up" "4694": "Announce AndrewJDR's annotated_cpp repository" --- name: "day288" title: "Finishing Brains" markers: "60": "Recap and set the stage for the day" "161": "handmade_sim_region.cpp: Introduce GetOrAddBrain" "435": "handmade_sim_region.cpp: Introduce a GetHashFromID for brain_id" "543": "handmade_sim_region.cpp: Remove AddEntityRaw and inline AddEntity's functionality in BeginSim" "704": "handmade_entity.h: Move struct brain in from handmade_sim_region.h, add an array of Parts to it, and introduce brain_hero_parts" "988": "Run the game and find that nothing happens" "1009": "handmade_world_mode.cpp: Set the Head and Body for BrainHero in AddPlayer" "1061": "Run the game and spam the world with heroes" "1212": "Blackboard: ddP and the benefit of assigning accelerations before simulating them together" "1356": "handmade_entity.h: Add ddP to entity" "1428": "handmade_world_mode.cpp: Make the controller code in UpdateAndRenderWorld just get the controller that corresponds to the given hero" "1686": "handmade_world_mode.cpp: Be Mr Slypants Slypantsyman and base the ControllerIndex in UpdateAndRenderWorld on the Brain->ID.Value" "1783": "handmade_entity.h: Introduce reserved_brain_id" "1871": "handmade_world_mode.cpp: Make AddPlayer take BrainID and return void" "1989": "Run the game and find that we can change the hero's facing direction" "2024": "handmade_world_mode.cpp: Remove BrainID, ddP, dSword, dZ, Exited and DebugSpawn from controlled_hero in from handmade.h and make UpdateAndRenderWorld initialise them directly" "2300": "handmade.h: Add BraidID back to controlled_hero" "2460": "handmade_world_mode.cpp: #if 0 the Planted code in UpdateAndRenderWorld" "2540": "Debugger: Investigate how we got into Hopping mode without a CameFrom" "2826": "handmade_sim_region.cpp: Reenable and fix ConnectEntityPointers" "2909": "Debugger: Break into UpdateAndRenderWorld and investigate how Occupying is being set to 0" "2997": "Hunt this guy down before stopping" "3035": "handmade_sim_region.cpp: Make ConnectEntityPointers able to break on Entity->ID.Value 219" "3145": "handmade_world.cpp: Make PackEntityIntoChunk do the same for the Source" "3284": "handmade_world_mode.cpp: Make AddPlayer put the Body and Head in their correct BrainSlot" "3349": "handmade_entity.h: #define BrainSlotFor in order to name the slots using pointer arithmetic" "3625": "Rant on compiler vendors making programmers' lives difficult" "3692": "handmade_entity.h: Introduce BrainSlotFor_ to return a brain_slot" "3751": "Q&A" "3768": "Can we have a look at the ctime stats so far?" "3879": "What will we do for the "production" Assert?" "3896": "May this brain system allow for things like two characters carrying a felled tree between them, with both of their brains controlling the movement of the tree?" "4076": "Try not to make the brains self-aware. We can't have stumpy over there taking over the world" "4102": "For brain types, why not an enum for the array indexes?" "4297": "How would you go about making game entities moddable?" "4352": "I was thinking defining whole new types of entities" "4460": "I guess there's no way to mitigate dll security concerns?" "4560": "So all the brain code is now in the switch(Brain->Type). How many brains do you expect to have? What if we have 100 brains, will you keep all the code there?" "4598": "We are out of time" --- name: "day289" title: "Decoupling Visuals from Entity Types" markers: "80": "Recap and set the stage for the day" "152": "A few words on deciding when to make new files" "238": "handmade_brain.h and handmade_brain.cpp: Add these files and pull in the brain code from handmade_entity.h and handmade_world_mode.cpp" "398": "handmade_brain.cpp: Introduce ExecuteBrain" "529": "handmade_world_mode.cpp: Consider how to deal with HeroesExist" "608": "4coder: Bug with buffer position loss" "687": "handmade_world_mode.cpp: Make UpdateAndRenderWorld set HeroesExist by looping through the controllers" "1017": "handmade_world_mode.cpp: Shuffle UpdateAndRenderWorld and delete superfluous code" "1141": "handmade_brain.cpp: Move the Planted mode code in from handmade_world_mode.cpp" "1313": "handmade_entity.h: Add ddtBob and MoveSpec to entity" "1597": "handmade_brain.cpp: Make ExecuteBrain give the head some movement" "1824": "handmade.cpp: Add ddP to controlled_hero" "1955": "Debugger: Investigate why we're not getting any acceleration" "2087": "handmade_world_mode.cpp: Make UpdateAndRenderWorld correctly set the ddP" "2165": "Run the game and move around" "2205": "handmade_brain.cpp: Move in the Familiar, FloatyThingForNow and Monstar code from handmade_world_mode.cpp" "2388": "handmade_world_mode.cpp: Figure out a way to get rid of Entity->Type and remove the Stairwell and Floor types" "2529": "handmade_world_mode.cpp: Allow anyone to draw their collision rectangles" "2557": "Run the game and view the collision rectangles" "2633": "handmade_world_mode.cpp: Compress these entity types" "2776": "handmade_entity.h: Introduce entity_visible_piece" "3028": "handmade_world_mode.cpp: Reimplement the Wall using entity_visible_piece" "3224": "Run the game and see no walls" "3237": "handmade_world_mode.cpp: Make AddWall call AddPiece" "3288": "Describe this process of enabling entities to prescribe how they will be rendered" "3337": "handmade_world_mode.cpp: Introduce AddPiece" "3446": "Run the game and see the trees" "3465": "handmade_world_mode.cpp: Temporarily make AddWall apply some EffectsEntropy to the Piece->Color" "3557": "Run the game and admire the randomly coloured trees" "3612": "Q&A" "3725": "Recently came across this. Please read the abstract and tell me what you think" "3888": "Is there a limit to the colors you can have?" "3933": "Will you need to have an entity type at some level, like when generating the world, placing trees and whatnot?" "4005": "Consider the reaps paper" "4171": "Colors of the trees, the hero, enemies, etc." "4202": "I've been a little lost the last few days. Would you mind giving a brief recap of what you're trying to do to the entity system now?" "4404": "Thoughts on avoiding denormalized floating-point on console platforms? Do they all have a -ffast-math?" "4461": "My apologies. Yes, limits in the game design" "4501": "Can you explain the difference between how you manage memory at work and how you're currently doing it in Handmade Hero?" "4514": "Will monsters and other things be able to attack each other (friendly fire), like a witch accidentally shrinks a goblin or something?" "4536": "Would we do anything differently if we wanted to have HDR capabilities in the game?" "4585": "Can you answer my previous question? People would like to see your pre-streams on YouTube" "4631": "The reason I ask is because I really like the idea of allocating up front and managing all memory myself as in Handmade Hero, but I'm not sure if I'm just shooting myself in the foot by not using malloc / free" "4823": "Wrap it up" --- name: "day290" title: "Finishing Separated Rendering" markers: "61": "handmade_sim_region.cpp: Remove the EntityOverlapsRectangle call in BeginSim" "238": "Run the game and set the stage for moving all the entities to the new path" "285": "handmade_brain.cpp: Make ExecuteBrain use the ddP2 rather than the ddP" "431": "handmade_world_mode.cpp: Make AddPiece take an Offset" "541": "handmade_world_mode.cpp: Make AddMonstar call AddPiece" "761": "Run the game and see the Monstar" "804": "handmade_world_mode.cpp: Make AddPlayer call AddPiece" "902": "handmade_world_mode.cpp: Consider how to proceed with the HeroBody and Familiar" "1023": "handmade_world_mode.cpp: Make AddPlayer do AddPiece calls for the Shadow, Torso and Cape, leaving out the animated portion of it" "1240": "Run the game and see everyone but the Familiar" "1265": "handmade_world_mode.cpp: Make AddFamiliar call AddPiece" "1342": "Run the game and see everyone" "1382": "handmade_entity.h: Introduce entity_visible_piece_movement with AxesDeform and BobOffset" "1458": "handmade_world_mode.cpp: Make the Familiar set the BobOffset flag, and the Hero set the AxesDeform one for the Cape" "1558": "handmade_world_mode.cpp: Make the HeroBody do AxesDeform" "2132": "handmade_world_mode.cpp: Make BeginLowEntity correctly set the axes" "2185": "Run the game and see that we're properly deforming" "2204": "handmade_entity.h: Remove entity_type from entity and see who needed it" "2353": "Run the game with the notion of entity_types gone" "2764": "handmade_brain.h: Introduce brain_hero, brain_monstar and brain_familiar" "2850": "handmade_world_mode.cpp: Make a Brain_Familiar case" "3198": "handmade_brain.h: Make BrainSlotFor_ take Type" "3285": "handmade_entity.h: Remove BrainType from entity and deal with the resultant compile errors" "3402": "Run the game and find that nothing has changed" "3409": "Q&A" "3453": "Were you trapped in an elevator today?" "3467": "If you are nuking the concept of an entity type but still keeping everything tightly bound in the brain, what real gain does all of this work give us? Didn't we just shift responsibility into the brain?" "3589": "After all this time, are finally you used to programming live? Is this a comfortable habit now?" "3627": "Could you explain again what you just did with the brain slot? That went a little fast for me" "3842": "How would you handle something like mind-controlling other entities, or having your mind swapped into a differently-structured body?" "4000": "handmade_brain.cpp: Implement mind control in ExecuteBrain" "4166": "handmade_brain.h: Introduce NoBrain" "4290": "Run the game and take control of the familiar" "4349": "handmade_brain.cpp: Make ExecuteBrain swap the BrainID and BrainSlot" "4512": "handmade_world_mode.cpp: Make PlayWorld set everything to NullCollision" "4550": "Run the game and toggle between the familiar and the original hero" "4598": "handmade_world_mode.cpp: Make AddMonstar set a brain" "4623": "Run the game and mind-control the monstar and the familiar" "4683": "When will we implement the zombie brain?" "4726": "Wrap it up" --- name: "day291" title: "Hopping Monstar and Occupying Trees" markers: "108": "Run the game and set the stage for the day" "197": "handmade_brain.cpp: Give ExecuteBrain the ability to move the Monstar" "373": "handmade_world_mode.cpp: Make AddMonstar take a traversable_reference" "490": "handmade_world_mode.cpp: Make AddStandardRoom call AddMonstar" "764": "Run the game and see that the Monstar doesn't appear to be initialised correctly" "823": "handmade_world.cpp: Make PackEntityReference leave the Index the same if there's no SimRegion and no GetHashFromID" "892": "Run the game and see that the Monstar is no properly occupying a square" "898": "handmade_brain.cpp: Enable the Monstar to move, run the game and watch it move" "939": "handmade_world_mode.h: Add random_series GameEntropy to game_mode_world" "975": "handmade_world_mode.cpp: Make PlayWorld initialise GameEntropy and use that GameEntropy to generate the rooms" "1015": "handmade_brain.cpp: Make ExecuteBrain set the Monstar's Delta using the GameEntropy and take game_mode_world *WorldMode" "1300": "Kick back and eat some cheesy poofs while watching the Monstar hop around randomly" "1422": "handmade_world_mode.cpp: Introduce struct standard_room, and make AddStandardRoom return it and specify the StandingOn points" "1792": "handmade_world_mode.cpp: Make AddWall take world_position P and traversable_reference StandingOn, and specify that the Tree occupies squares" "1847": "Run the game and find that the Monstar cannot hop on the Trees, but that we can currently hop over them" "1931": "handmade_world_mode.cpp: Make the Head collide with the Trees" "2035": "handmade_brain.cpp: Stop ExecuteBrain checking for deletion and doing unnecessary controller code" "2271": "handmade_brain.cpp: Investigate why the Head is sticking by adding a DEBUG_B32 for NoPush and a DEBUG_VALUE for ddP2, and setting the Head's UnitMaxAccelVector to false" "2529": "Run the game and hit the Assert relating to MaxEntityVelocity" "2679": "handmade_sim_region.cpp: Stop MoveEntity taking the move_spec" "2821": "handmade_brain.cpp: Stop entity taking the move_spec" "2864": "handmade_brain.cpp: Change how ExecuteBrain sets the Head's ddP" "3280": "Run the game and find that we've fixed the bug" "3341": "handmade_world_mode.cpp: Make AddStandardRoom call AddFamiliar and make AddFamiliar take world_position P and traversable_reference StandingOn" "3427": "Run the game and see our Familiar occupying its square" "3452": "handmade_entity.h: Remove Moveable from entity_flags" "3537": "Q&A" "3590": "Why are the textures not loading properly sometimes?" "3651": "Why the decision to make the game grid-based?" "3660": "There were sirens earlier. Is #manintree back at it again?" "3675": "Do you think even after getting a four-year degree in MIS it's worth it to learn a language such as C#?" "3704": "I guess technically if the gameplay is centered around tiles and facing direction, you wouldn't necessarily need collision detection?" "3775": "What are the 18 threads that run with the game?" "4040": "What is going to replace the ground splat system? Just different tile types and seamless textures?" "4061": "Why don't you program in a UNIX-based OS?" "4240": "Why wouldn't multithreading work all that well? Complications? Limitations?" "4268": "How did you manage to make thinks work in Windows when you started your career, given that MSDN at least now is negligible or unreliable or both?" "4316": "A few words on the giant splatter of garbage that is the Windows API" "4415": "You said something about the multi-threading being funky?" "4448": "Do you have positive or negative thoughts when it comes to learning and using Python for building applications?" "4464": "MSDN came on 2 CDs" "4504": "Which programming languages do you use regularly?" "4535": "Thanks" --- name: "day292" title: "Implementing Snakes" markers: "74": "Recap and plan to implement a floating method of movement and make a snake" "209": "handmade_entity.h: Add MovementMode_Floating to entity_movement_mode" "288": "handmade_brain.cpp: Enable the Familiar to move towards the closest Hero" "346": "Debugger: Step into Type_brain_familiar and note that Type_brain_hero is the default value" "531": "handmade_brain.h: Introduce IsType and make the Familiar check for the Hero type" "672": "Run the game and see the Familiar orbit the Hero" "803": "handmade_world_mode.cpp: Introduce AddSnakePiece" "897": "handmade_brain.h: Introduce brain_snake" "1004": "handmade_brain.h: #define IndexedBrainSlotFor" "1256": "handmade_sim_region.h: Replace the entity *Array[16] in brain with a *Array" "1380": "Rant on pointer arithmetic in C++" "1454": "handmade_sim_region.cpp: Advance the Ptr through the Brain->Array, ensuring that it remains inside the Brain structure" "1626": "Underscore the necessity of languages to make simple operations easy to program" "1838": "handmade_world_mode.cpp: Make AddStandardRoom add a snake by calling AddSnakePiece" "1974": "handmade_brain.cpp: Make ExecuteBrain move the snake" "2306": "Run the game and see the Snake moving like a Monstar" "2318": "handmade_world_mode.cpp: Add more snake pieces" "2390": "Run the game and see the snake moving around just fine, until it traps itself" "2591": "handmade_world_mode.cpp: Try creating some additional screens" "2596": ""We have a lot of N-squaredy things"" "2760": "Run the game and watch the simulation" "3085": "Consider encouraging entities to move towards us from adjacent rooms" "3402": "todo.txt: Update the TODOs and add an Entity System note for geographically disparate entities" "3534": "Q&A" "3583": "Wasn't today an off-day?" "3609": "Can the compiler really mess up the pointer arithmetic? I mean, it is just integer ops, can't be that hard to mess up" "3748": "So is the way to fix the snake from getting stuck to just allow it to run over itself or to make the snake AI smart enough to not trap itself?" "3828": "I've recently watched your video on the GJK algorithm, it's great, thanks for that! Did you also do a video on the EPA algorithm?" "3842": "Will the snake head be able to move to the position of its last segment? So it can go in a circle / loop" "3890": "WTF you did a video on GJK? What other explanation videos have you done?" "3909": "Are you going to implement every AI thing in brain entity? When does path-finding and rest of AI coming on schedule? Also can you say some good reference book for AI? Cheers, Casey" "4007": "Yeah, and IMGUI, but what else?" "4038": "Expanding Polytope Algorithm" "4149": "Could you briefly explain how a snake segment knows which node to jump to? A non head segment, that is" "4165": "Don't forget the API video!" "4270": "Well I've got GJK + EPA implemented in 2D and GJK in 3D, but I am a bit struggling at EPA in 3D" "4343": "Wrap it up" --- name: "day293" title: "Moving Familiars" markers: "122": "Recap and set the stage for the day" "322": "handmade_entity.h: Add MovementMode_Floating to entity_movement_mode" "600": "Consider where the delineation between MovementMode and Brain should be" "820": "handmade_brain.cpp: Enable ExecuteBrain to make the Familiar occupy traversables and do transactional movement" "1310": "Debugger: Step into Type_brain_familiar in ExecuteBrain and investigate why the Familiar isn't moving" "1480": "handmade_sim_region.cpp: Make GetClosestTraversable set Entity.Index" "1499": "Run the game and see the Familiar move" "1587": "Blackboard: Proportional Derivative (and Integral) Controller" "1831": "handmade_brain.cpp: Make ExecuteBrain set a spring on the Familiar" "1875": "Run the game and see the spring in action" "2111": "handmade_brain.cpp: Introduce the notion of a TargetTraversable which the Familiar moves towards" "2229": "handmade_sim_region.cpp: Introduce IsOccupied" "2330": "Run the game and see that the Familiar follows us" "2347": "handmade_world_mode.cpp: Make AddStandardRoom randomly offset the grid points" "2491": "Run the game and see the irregular grid, with everyone able to function on it" "2660": "handmade_sim_region.cpp: Introduce GetClosestTraversableAlongRay" "2799": "handmade_brain.cpp: Make ExecuteBrain call GetClosestTraversableAlongRay for the Familiar" "2944": "Run the game and see that the Familiar is more stable" "3020": "handmade_sim_region.cpp: Add a TIMED_FUNCTION for GetClosestTraversable and GetClosestTraversableAlongRay" "3066": "Run the game and view the profiler" "3163": "build.bat: Temporarily switch to -O2 and then run the game and see how that affects our performance" "3371": "handmade_sim_region.cpp: Introduce GetClosestEntityWithBrain and closest_entity" "3617": "handmade_brain.cpp: Make ExecuteBrain call GetClosestEntityWithBrain for the Familiar" "3704": "Run the game and see that it works beautifully" "3719": "Q&A" "3764": "Any thoughts on multithreading the entity system?" "3781": "++ and += to reduce memory useage..." "3967": "How many more times will you get hit with the texture upload issue before you actually fix it?" "4002": "Do you have a max entity count at the sim region on the debug display?" "4166": "(Out of topic) Milton seems to be treating Wacom input as mouse input. Restart Milton? Will look into it" "4240": "Close things down" --- name: "day294" title: "Adding the Glove" markers: "48": "Prepare for combat" "461": "handmade_world_mode.cpp: Make AddPlayer initialise a Glove and call AddPiece for it" "633": "handmade_brain.h: Add Glove to brain_hero" "660": "handmade_world_mode.cpp: Make PlayWorld set the Glove to not collide" "799": "handmade_brain.cpp: Make ExecuteBrain position the glove next to the hero's body" "1030": "handmade_brain.cpp: Make ExecuteBrain offset the Glove according to the hero's FacingDirection" "1129": "Blackboard: Calculating the angle relative to the FacingDirection" "1237": "Run the game and see the "glove"" "1363": "handmade_brain.h: Add MovementMode_AttackSwipe to entity_movement_mode" "1473": "handmade_world_mode.cpp: Implement the AttackSwipe in UpdateAndRenderWorld" "1584": "Blackboard: Parameterising the arc of the swipe" "1710": "handmade_entity.h: Add SwipeAngleStart and SwipeAngleTarget to entity" "1836": "handmade_entity.h: Add MovementMode_AngleOffset and MovementMode_AngleAttackSwipe to entity_movement_mode" "2503": "handmade_brain.cpp: Provide the ability in ExecuteBrain to initiate an attack" "2749": "Run the game and try out the swipe" "2895": "handmade_entity.h: Add AngleCurrentDistance, AngleBaseDistance and AngleSwipeDistance to entity" "2931": "handmade_world_mode.cpp: Make UpdateAndRenderWorld parameterise the swipe's arc" "3046": "handmade_math.h: Introduce Sin01" "3099": "Blackboard: Cosine arc" "3333": "Run the game and try out the swipe" "3562": "handmade_math.h: Introduce Triangle01" "3626": "handmade_world_mode.cpp: Make UpdateAndRenderWorld call Triangle01 and then run the game to try it out" "3664": "Q&A" "3707": "Will it support Nintendo's power gloves?" "3737": "Are chain attacks going to be in by any chance (i.e. slash slash thrust)?" "3796": "What are your thoughts on switching to simulating adjacent rooms rather than using the simulation apron?" "3919": "How is the familiar intended to attack? Some kind of projectile or doing some kind of glide move and physically hitting a foe?" "4001": "Will there be a boot to match the glove?" "4007": "For the particle effects for the glove, are we going to be doing something similar to what we did earlier using head assets?" "4068": "I'm wondering if it could be a cool mechanic if you could swipe and change your facing direction while you swipe, thus prolonging the swipe into a potentially never ending spinning punch..." "4122": "Have you played Planescape: Torment? Handmade Hero totally needs a Morte-style familiar" "4164": "Will attacking be interrupt? Such as attacking unanimated entity, or someone attacked the player from behind and it jump opposite to the attack (e.g. old Zelda)?" "4245": "Why not leave the glove swipe to the artist / animator of the game?" "4348": "Wind down, with a glimpse into the future and some thoughts on how alive the world is starting to feel" --- name: "day295" title: "Stacking Rooms for Z Layer Debugging" markers: "11": "On determining which systems impact many other systems, and solidifying them early on" "165": "What Mike Acton had to say about the potential costliness of some game design decisions" "463": "Recap our current situation and set the stage for solidifying Z" "594": "handmade_world_mode.cpp: Make AddStandardRoom generate some stairs" "959": "Run the game and traverse the offset stairs" "991": "handmade_world_mode.cpp: Make PlayWorld generate more layers of rooms" "1038": "Run the game and see the multiple layers" "1094": "handmade_world_mode.cpp: Expand the TraversablePoint rectangles to fill the tiles and give them outlines" "1350": "handmade_render_group.cpp: Make PushRect multiply the Color by GlobalAlpha" "1371": "Run the game and see that we're already in pretty good shape, but need to more clearly specify Z" "1482": "handmade_world_mode.cpp: Make AddStandardRoom generate a hole in the ground" "1755": "Run the game and look down through the hole" "1801": "The snake just went up the stairs" "1824": "handmade_world_mode.cpp: Make UpdateAndRenderWorld draw the tiles green" "1897": "Run the game and consider the problem with drawing down so far" "2008": "handmade_world_mode.cpp: Make UpdateAndRenderWorld expand FadeBottomStartZ and FadeBottomEndZ" "2061": "Profiler: Note that BeginSim and UpdateAndRenderWorld are slow" "2308": "build.bat: Switch to -O2 find that we're now running at 60 FPS" "2399": "Profiler: Switch to the software renderer" "2461": "win32_handmade.cpp: Add more BEGIN_BLOCK and END_BLOCK pairs in Win32DisplayBufferInWindow" "2604": "handmade_world_mode.cpp: Add more BEGIN_BLOCK and END_BLOCK pairs in UpdateAndRenderWorld" "2652": "Run the game, view those timings and find that brains are not taking much time" "2704": "handmade_debug.cpp: Make DrawTopClocksList calculate and display a cumulative percentage" "2859": "handmade_debug.cpp: Make DrawTopClocksList call AddTooltip to draw this percentage" "3126": "Debugger: Step into DrawTopClocksList and find and investigate why our TextRect is not valid" "3296": "handmade_debug.cpp: Make DrawTopClocksList set TextRect off GetTextSize" "3359": "handmade_debug_ui.cpp: Introduce a version of GetTextSize that takes a v2 At" "3399": "handmade_debug_ui.cpp: Make AddTooltip draw a background" "3520": "handmade_debug.cpp: Make ToolTipTransform appear above everything" "3628": "Run the game and view our tooltip" "3768": "handmade_sim_region.cpp: Add a TIMED_BLOCK for SimUnpack in BeginSim" "3797": "handmade_sim_region.cpp: Make the PushArray calls in BeginSim do NoClear, and check that all of the necessary data is initialised" "3942": "Profiler: Find that BeginSim no longer takes so much time" "4012": "handmade_world_mode.cpp: Add BEGIN_BLOCK and END_BLOCK pairs for EntityRendering and EntityPhysics in UpdateAndRenderWorld" "4098": "Profiler: Find that EntityRendering is taking up the lion's share of the time" "4267": "handmade_world_mode.cpp: Move the EntityRendering block down to look only at the Piece list" "4296": "handmade_world_mode.cpp: Add BEGIN_BLOCK and END_BLOCK pairs for CollisionRendering, VectorClear, and HitpointRendering in UpdateAndRenderWorld" "4353": "Profiler: Find that CollisionRendering is the hog" "4367": "handmade_world_mode.cpp: Add BEGIN_BLOCK and END_BLOCK pairs for VolumeRendering and TraversableRendering in UpdateAndRenderWorld" "4414": "Profiler: Find that TraversableRendering is the most expensive" "4473": "handmade_world_mode.cpp: #if 0 the PushRectOutline calls for the traversables" "4535": "Consider turning on the optimiser just for these traversable drawing routines or blowing out the PushRect functions to be more explicit" "4579": "Q&A" "4641": "insobot Do you have a question for me?" "4648": "cmuratori: Duuuuude" "4654": "How much longer does it take to build Handmade Hero with release optimizations?" "4704": "Debugger: Demo the insufficiency of MSVC's debug information in optimised builds" "4979": "The switch is -Zo" "5026": "I missed the optimization due to buffering but I caught some stuff about the clear being bloated, but didn't catch what the fix was?" "5053": "Far-away floors turning transparent don't look quite right since you can see through them" "5083": "When peering down the hole at the more transparent layers, you can see characters through those ground layers. My guess is you would want to mix with a "fog color" instead of just making the tiles transparent?" "5124": "Would LLVM work on Windows / Handmade Hero?" "5238": "What editor is most similar to 4coder, and how long did it take to pick it up?" "5302": "Having many levels of rooms and having entities in each level actively executing, wouldn't that be heavy / expensive? Or have you think in a performance solution or a level limitation?" "5357": "Is there a way to tell the compiler to optimize just a particular section of the code? If not, how would you work around that?" "5467": "Clang++ is worse. Honestly, why can't the PDB just say "Hey, you are at this instruction? Okay, the value is in this register / address or whatever"?" "5626": "Wind it down" --- name: "day296" title: "Fog and Alpha for Layers" markers: "127": "Recap and set the stage for the day" "216": "handmade_world_mode.cpp: Set Volumes to not be Upright in UpdateAndRenderWorld" "278": "Run the game and see the difference that makes" "571": "handmade_render_group.h: Make GlobalAlpha in render_group a v4 and rename it to GlobalModulate" "641": "Consider clearly distinguishing between colours that have premultiplied alpha and those that don't" "759": "handmade_render_group.cpp: Introduce StoreColor and make PushBitmap, PushRect and Clear call it" "865": "Blackboard: Hadamard Product" "1025": "handmade_render_group.h: Add tGlobalColor and GlobalColor to render_group to allow us to do a linear blend as well as a modulate" "1208": "handmade_render_group.cpp: Pass the Group to the StoreColor calls" "1271": "Blackboard: Fade vs Haze" "1342": "handmade_world_mode.cpp: Conditionally compute the tGlobalColor and GlobalColor for fade and haze in UpdateAndRenderWorld" "1511": "Run the game and note that we're not handling alpha multiplication correctly" "1564": "handmade_render.cpp: Stop DrawRectangle, DrawRectangleSlowly and DrawRectangleQuickly from premultiplying the alpha" "1640": "handmade_render_group.h: Rename Color to PremulColor where appropriate" "1781": "Run the game, see that our two renderers draw solid filled rectangles in different colours and investigate why this is the case" "2272": "handmade_render.cpp: Try not squaring the Color when modulating incoming Color in DrawRectangle" "2361": "handmade_render.cpp: Try Squaring the Color up front in DrawRectangle" "2557": "handmade_render.cpp: Try multiplying all the Colors by 255 again" "2605": "Run the game and see that that's almost exact" "2618": "Blackboard: Ensuring that we remain in the same colour space" "2843": "Debugger: Step into UpdateAndRenderWorld when CameraRelativeP.z > FadeTopStartZ and inspect the Color values" "3159": "handmade_opengl.cpp: Try rendering everything at 50% opacity" "3327": "Debugger: Step into OpenGLRectangle and inspect the Entry->PremulColor values" "3428": "handmade_render_group.h: Conditionally add DebugTag to render_group_entry_header and render_group if we are in HANDMADE_SLOW mode" "3610": "handmade_world_mode.cpp: Make UpdateAndRenderWorld set DebugTag to 1 if CameraRelativeP.z > FadeTopStartZ" "3666": "Debugger: Break into our BreakHere line in OpenGLRenderCommands" "3738": "handmade_world_mode.cpp: Negate the alpha of tGlobalColor for the fade" "3776": "Run the game and see that the fade is now correct" "3842": "Investigate why we are seeing nothing below our level" "4052": "handmade_world_mode.cpp: Enable the correct blending in UpdateAndRenderWorld" "4075": "handmade_world_mode.cpp: Initialise a BackgroundColor in UpdateAndRenderWorld and pass this to Clear and the GlobalColor for the lowest floors" "4135": "Run the game and see the haze happening" "4167": "Q&A" "4203": "One thing you could try is having the center of the perspective projection be the player's position, so things on other levels line up straight" "4229": "The Hadamard transform seems like it can be used for a lot of things. What is it doing in handmade_world.cpp in the subtract function?" "4256": "Blackboard: Hadamard Product ~= Diagonal Matrix" "4592": "For the record, a circle with an x would be the tensor product" "4645": "Would it be difficult to implement textured or just different fog colors, so you could make, for instance, vignetted fog?" "4786": "How did you finally discover the gamma correction bug? What was the clue that made you say ah ha?" "4865": "Wind it down" --- name: "day297" title: "Separating Entities into Z Layers" markers: "64": "Recap and set the stage for the day" "130": "Demo the problem with alpha blending textures separately" "260": "handmade_render_group.h: Consider adding slice information to render_entry_cliprect" "423": "handmade_world_mode.cpp: Consider specifying relative floor layers" "724": "handmade_world_mode.cpp: Make UpdateAndRenderWorld loop over the LevelIndex, using PushClipRect to set the ClipRectIndex" "1068": "handmade_render_group.h: Introduce transient_clip_rect" "1241": "handmade_world_mode.cpp: Make UpdateAndRenderWorld put the three main layers into a different ClipRectIndex" "1404": "handmade_entity.cpp: Introduce UpdateAndRenderEntities" "1808": "handmade_world_mode.cpp: Make UpdateAndRenderWorld call UpdateAndRenderEntities" "1840": "handmade_entity.cpp: Test the clipping by halving the size of the screen for the current layer" "1968": "Run the game and see that we're clipped to the lower part of the screen" "2056": "handmade_entity.cpp: Make UpdateAndRenderEntities compute CameraRelativeGroundZ per LevelIndex" "2331": "handmade_entity.cpp: Set the CameraRelativeGroundP in UpdateAndRenderEntities immediately before rendering" "2544": "handmade_entity.cpp: Extract RelativeLayer from OffsetP.z in UpdateAndRenderEntities" "2754": "handmade_entity.cpp: Make UpdateAndRenderEntities set CameraRelativeGroundZ based on the Origin" "2965": "handmade_entity.cpp: Introduce ConvertToLayerRelative" "3209": "handmade_render_group.h: Introduce clip_rect_fx" "3269": ""We can handle it"" "3275": "Consider reducing the system down to two slices" "3554": "handmade_render_group.cpp: Make PushClipRect take a clip_rect_fx" "3606": "Run the game and see that the slices are not being perspective transformed" "3649": "Q&A" "3688": "I added some preliminary moderation code to insobot. At the moment it will just print out when it would time out" "3804": "It's been a while, did I see you programming without wrist braces? Are you not affected anymore?" "3984": "Is Jeff Atwood a good programmer?" "4107": "When you were working on switching between the software and hardware renderer yesterday, why did it look like there was still a very slight color difference?" "4199": "What would you say are the top three things that have made Molly Rocket successful in your eyes from a startup / business perspective?" "4386": "Do you mind name dropping her? I live in Seattle too and have a new wrist issue with programming" "4557": "As someone back at Episode 054, how far gone am I? Haha, just kidding. Thanks for everything, Casey!" "4595": "Do you find that your hands shake when holding a drinking glass? That's the only time my hands shake at all" "4635": "Wind it on down" --- name: "day298" title: "Improving Sort Keys Part 1" markers: "37": "On the two kinds of Z-values necessary for presenting multiple layers of rooms to the viewer" "159": "Recap and set the stage for the day" "376": "handmade_render_group.cpp: Look through how the perspective transform is currently programmed" "487": "Blackboard: Handling the "Changeover Point" between floors" "840": "Blackboard: Sorting entities in Y and Z using a "Hotpoint Rule"" "1485": "Blackboard: Consider these cases for any possible insights" "2183": "Blackboard: Placing the sort point differently depending on whether or not the entity is upright" "2348": "handmade_render_group.cpp: Look through PushBitmap to see how it currently does the sort" "2502": "handmade_render_group.cpp: Make GetRenderEntityBasisP calculate the SortKey using a PerspectiveZ, DisplacementZ, PerspectiveSortTerm, YSortTerm and ZSortTerm" "3358": "Consider the risk of having two important points on a bitmap, and to what degree they tend to line up" "3404": "Blackboard: Sorting multi-segment bodies" "3479": "handmade_render_group.cpp: Introduce ComputeSortKey in order to facilitate correct sorting of articulated figures" "3597": "handmade_render_group.cpp: Revert changes in GetRenderEntityBasisP for the time being" "3678": "Run the game and see the havoc" "3738": "handmade_entity.cpp: Plan for handling articulated figures next week" "3931": "Q&A" "3972": "Kind of didn't get it from the email - are you still up to putting a break sometime soon and make a little intro series to programming?" "4038": "Another use case to consider for the Y- / Z-sorting: "flat" things laying on top of other "flat" things (like a rug on a floor). How would the Y-sort position be set in this case, especially if the thing on top was larger than the thing(s) it was laying on?" "4143": "You wanted to go a bit more serious than Intro to C early on. Maybe you changed your mind since" "4158": "What do you think of representing entities as 3D objects to keep things simple? Like cylinders for characters, and cubes for tiles and rooms?" "4266": "Blackboard: Sorting rugs and floors" "4484": "Blackboard: Considering this in 3D" "4633": "Maybe you need to sort the objects separately in both Y and Z and then solve the conflicts if an object A is before object B in the Y-sort and in reverse order in the Z-sort?" "4828": "Close down, to be continued..." --- name: "day299" title: "Improving Sort Keys Part 2" markers: "11": "Recap and set the stage for the day" "111": "Blackboard: Tile Z Sorting" "158": "Blackboard: How to sort when looking directly top-down" "368": "Blackboard: The complication that arises from tilting the camera" "509": "Blackboard: Quantising entities to tiles" "614": "Blackboard: The problem with rugs" "782": "Blackboard: Painter's Algorithm" "875": "Blackboard: The cases of the rug situation" "1323": "Blackboard: Top-down 2D vs 3D" "1621": "Blackboard: Using planar maths" "1782": "Blackboard: Considering this as a 3-dimensional problem" "2162": "Blackboard: Flat vs Upright Entities" "2510": "Blackboard: The problem of Y inside a single cell" "2792": "Blackboard: The case with a tilted camera looking down on a hero standing on a rug" "2993": "Blackboard: Using the closest point entities have in common to determine the sorting" "3514": "Q&A" "3599": "If you're only concerned about sprites that exist on more than one cell, why not split the polygons on cell boundaries? There can't be that many / can't be that expensive?" "3748": "Wind down" --- name: "day300" title: "Changing from Sort Keys to Sort Rules" markers: "49": "How 2.5D Sorting Works in River City Ransom: Underground" "589": "On doing a semantic sort" "771": "handmade_render_group.h: Consider separating out the topological sorting from the render group" "888": "handmade_entity.cpp: Consider making UpdateAndRenderEntities() draw pieces in front of other pieces" "1078": "Blackboard: Sorting Rules" "1226": "Blackboard: Considering the fact that we only need to sort sprites that overlap" "1285": "Blackboard: The three nominal cases involving Z planar and Y planar sprites" "1379": "Blackboard: Z overlaps Z" "1845": "Blackboard: Y overlaps Z" "2083": "Blackboard: Y overlaps Y" "2343": "Blackboard: Consolidating these cases" "2683": "Blackboard: Considering whether this scheme will allow us to sort completely" "3032": "handmade_sort.cpp: Introduce sort_sprite_bound and make MergeSort() take it" "3179": "handmade_sort.cpp: Introduce IsInFrontOf() in order to handle our three cases" "3727": "handmade_sort.cpp: Introduce a Swap() that takes sort_sprite_bound" "3758": "Q&A" "3778": "Isn't it Y (vertical) sprites that have YMin == YMax?" "3797": "handmade_sort.cpp: Correct the sense of BothZSprites in IsInFrontOf()" "3811": "You always do == float comparisons. How can you ensure those will ever return true because of float precision?" "3901": "In the Y overlaps Z case, what about cliff sides that are holding up the ground sprites (so elevated ground isn't just floating there)? Would that cause an issue with anything?" "3920": "Blackboard: Breaking problematic sprites into two pieces" "3997": "I literally did the "float ==" thing last week and considered it acceptable for that exact reason, because I was just checking if a value had just been set by me to an exact value on the previous frame or whatever" "4169": "Close it down" --- name: "day301" title: "Sorting with Sprite Bounds" markers: "2": "Recap and set the stage for the day" "277": "handmade_sort.cpp: Double check that the sense of IsInFrontOf() is correct" "346": "handmade_sort.cpp: Consider how to get sorting into layers for free, and turning the whole renderer into sprite-bound sorting" "575": "handmade_render_group.h: Consider excising SortKey entirely from entity_basis_p_result" "652": "handmade_render_group.cpp: Make PushRenderElement_() take a sort_sprite_bound rather than SortKey" "793": "handmade_sort.cpp: Separate sort_sprite_bound out into sprite_bound and make IsInFrontOf() take sprite_bound" "901": "handmade_sort.cpp: Consider which are the correct values to pass to PushBitmap()" "1034": "handmade_render_group.h and *.cpp: Delete SortKey from entity_basis_p_result" "1135": "handmade_render_group.cpp: Make PushBitmap() set the SpriteBound.YMin and .ZMax for Upright sprites" "1422": "handmade_render_group.cpp: Make PushBitmap() set the SpriteBound.YMin, .YMax and .ZMax for non-Upright sprites" "1528": "handmade_render_group.cpp: SpriteBound" "1592": "handmade_render_group.cpp: Consider making PushRect() do the same calculations as PushBitmap(), and make Clear() sort below everything" "1668": "handmade_render_group.cpp: Introduce GetBoundFor() and pull functionality into it from PushBitmap()" "1754": "Run the game and run into a world of hurt very quickly" "1804": "handmade_sort.cpp: Introduce GetSortEntries() in order to cast Entries to sort_sprite_bound" "1948": "handmade_render.cpp: Make SortEntries() call GetSortEntries() and no longer call RadixSort() in favour of MergeSort()" "2065": "handmade_render.cpp: Pull GetSortEntries() in from handmade_sort.cpp: and introduce GetSortTempMemorySize()" "2123": "win32_handmade.cpp: Make WinMain() call GetSortTempMemorySize()" "2193": "handmade_sort.cpp: Make SortEntries() a TIMED_FUNCTION()" "2255": "Debugger: Step into SortEntries() and inspect the SortKey values for EntryA and EntryB" "2462": "handmade_sort.cpp: #if 0 the HANDMADE_SLOW code in SortEntries(), run the game and see nothing" "2530": "handmade.cpp: Make GAME_UPDATE_AND_RENDER() just play the Cutscene" "2580": "Debugger: Break into SortEntries() and ensure that the sense of the IsInFrontOf() and MergeSort() are correct" "2843": "build.bat: Disable HANDMADE_INTERNAL and #define DEBUG_ macros in handmade_debug_interface.h" "2946": "Debugger: Break into SortEntries() and inspect the SortKey() values for the first 8 Entries" "3023": "Mini Owl of Shame Moment: This is not a front-to-back renderer" "3054": "handmade_sort.cpp: Make IsInFrontOf() sort in the correct direction" "3107": "Run the game and find that our fundamentals are not completely messed up" "3155": "handmade.cpp: Make GAME_UPDATE_AND_RENDER() go straight to the game, and then run the game and determine that we never fail our check in an obvious linear sweep" "3216": "handmade_entity.cpp: Make UpdateAndRenderEntities() draw entities in Z without flattening them to the plane" "3279": "Run the game and find that we're not getting the expected sort" "3305": "build.bat: Enable HANDMADE_INTERNAL" "3368": "Q&A" "3425": "Hey Casey, managed to make the stream today. Just wanted to pop in and say hi" "3520": "The coordinates used for the sort rules are world space, right? Would another approach be to sort the screen space coordinates from the top of the screen down?" "3554": "Blackboard: Cases against being able to sort screen space without Z" "3886": "I have a question about your development approach: I don't think I've ever seen you create a separate program or environment to test stuff. You always seem to work within the running game. Do you ever find this "noisy"?" "4217": "I realise I tell a lie now. I have seen you do something along those lines on Witness Wednesdays, just less so on Handmade Hero" "4367": "How do you clean all the directories without deleting them?" "4465": "Demo Math Visualizations" "4980": "That was really awesome to see! Thanks!" "5008": "Close it on up" --- name: "day302" title: "Confirming No Total Ordering" markers: "75": "handmade_render_group.cpp: Correctly compute the SpriteBound values in GetBoundFor()" "143": "Recap and set the stage for the day" "402": "handmade_render_group.cpp: Enable SortEntries() to do a total ordering check" "734": "Run the game, try doing the new check and hit our Assertion" "766": "Debugger: Inspect the SortKey values for EntryA and EntryB" "928": "handmade_sort.cpp: Temporarily change the Assert in SortEntries() to a BreakHere, and count the SortErrors" "1042": "Debugger: Break into SortEntries() to see how many sort errors there were" "1093": "Blackboard: Sort Partial Ordering Problem" "1243": "Blackboard: Turning our Partial Ordering into a Total Ordering" "1440": "handmade_sort.cpp: Consider making IsInFrontOf() sort by distance from the camera" "1580": "Blackboard: Sorting by distance from the camera" "1783": "Blackboard: Orthographic camera" "1975": "Blackboard: Will taking the topmost point of cards be sufficient?" "2125": "handmade_sort.cpp: Introduce BuildSpriteGraph()" "2450": "Blackboard: Graph Theory" "2594": "Blackboard: Directed Graph" "2667": "Blackboard: Directed Acyclic Graph" "2803": "handmade_sort.cpp: Continue implementing BuildSpriteGraph()" "2985": "handmade_math.h: Introduce a version of RectanglesIntersect() that takes rectangle2" "3151": "handmade_sort.cpp: Consider partitioning the screen in order to build this graph and potentially using the Z-buffer" "3340": "handmade_sort.cpp: Consider leveraging the screen partitioning in order to optimise the software renderer" "3375": "Q&A" "3423": "How much more work would you have to do to get a full 3D sorting?" "3527": "I mean, use fake 3D data, since our cards are essentially flat, we can give an epsilon width to it for the sorting" "3555": "Blackboard: Sorting 3D objects" "3758": "Blackboard: Sorting all entities in a linear total ordering" "4255": "Blackboard: Common problematic cases in Handmade Hero" "4463": "Sorry if this was already answered, but what was the issue with a "return a_z != b_z ? a_z - b_z : a_y - b_y" style total ordering?" "4481": "Blackboard: The problem with sorting heroes behind walls on rugs on tiles" "4742": "Would the Y then Z sort work if Z is quantized to room layers, and sprites are split where they cross layers (and maybe the ground is special cased)?" "4810": "Wind it down" --- name: "day303" title: "Trying Separate Y and Z Sorts" markers: "50": "Be our own code fairy" "76": "Recap and set the stage for the day" "117": "Z-buffering is not a good idea for 2D stuff" "248": "quartertron's sorting suggestion, or potentially using an insertion sort to make a poor man's binary space partition" "424": "Blackboard: Separately sorting Z-sprites and Y-sprites, then merge sorting those sorted sprites" "863": "handmade_sort.cpp: Introduce versions of MergeSort() for MergeSortY() and MergeSortZ()" "1169": "handmade_sort.cpp: Introduce versions of IsInFrontOf() for IsInFrontOfY() and IsInFrontOfZ()" "1251": "Consider how to separate the Y- and Z-sprites" "1406": "handmade_sort.cpp: Make MergeSort() separate the Y- and Z-sprites" "1452": "Blackboard: Separating and compacting an array" "1514": "handmade_sort.cpp: Continue making MergeSort() separate out those sprites" "1675": "Blackboard: The sizes of the two arrays" "1748": "handmade_sort.cpp: Make MergeSort() call MergeSortY() and MergeSortZ()" "1861": "Blackboard: Copies of the sorted stuff" "1917": "handmade_sort.cpp: Consider making MergeSortZ() copy to the Temp buffer" "2004": "handmade_sort.cpp: Make MergeSort() copy to the Temp buffer if there are 1 or 2 Z-sprites to be sorted" "2356": ""It's no skin off our back"" "2358": "handmade_sort.cpp: Clean up compile errors" "2481": ""We probably need to go through this code more carefully"" "2534": "Run the game and see that we are sort of anywhere close" "2571": "Run the game and hit the assertion in SortEntries()" "2621": "Debugger: Break into MergeSort() and inspect the YCount and ZCount" "2702": "handmade_sort.cpp: Give MergeSort() some verification tests" "2731": "handmade_sort.cpp: Introduce IsZSprite()" "2787": "handmade_sort.cpp: Continue giving MergeSort() these tests" "2825": "Debugger: Break into MergeSort() and find that it passed the tests" "2839": "handmade_sort.cpp: Introduce VerifyBuffer() to verify the type of sprites in that buffer, and make MergeSort() call it" "2963": "Debugger: Break into MergeSort() again and find that everything is in the right place" "2998": "Consider making a better merge" "3098": "Blackboard: What the sort is doing" "3190": "handmade_sort.cpp: Look at what IsInFrontOf() is doing" "3328": "handmade_sort.cpp: Make VerifyBuffer() verify that the sprites are correctly sorted" "3386": "Debugger: Run the game and hit the assertion in VerifyBuffer()" "3413": "A few words on "test driven development"" "3482": "Debugger: Break into VerifyBuffer() and inspect the positions of the sprites upon failing" "3578": "handmade_sort.cpp: Turn MergeSortY() into MergeSort() in order to do IsInFrontOf() in both cases" "3637": "handmade_sort.cpp: Rename MergeSort() to SeparatedSort(), and remove MergeSortZ() entirely" "3677": "Debugger: Run the game and catch some sprites that our test thinks are incorrectly sorted" "3759": "handmade_sort.cpp: Temporarily toggle SortEntries() to do only the partial ordering check" "3774": "Run the game and see the visual results" "3792": "Q&A" "3937": "I'm trying to take a different approach, using the projected sprites on the screen to sort, and using the min / max y values (up) as a depth sorting key" "3979": "Working on it" "4044": "What is a full stack developer?" "4208": "Won't sorting fail because a lower Z sometimes needs to be drawn on top of a higher Z if a Y-sprite overlaps them?" "4265": "Blackboard: PoohShoes's diagram" "4372": "At the start you mentioned "insertion sort" and potentially automatically getting a binary tree representation of the sprites. What happened to that idea, assuming I roughly understand correctly what you've done?" "4391": "Blackboard: Graph sort" "4489": "How do you transform the sprites from world to screen coordinates?" "4511": "That's it for today" --- name: "day304" title: "Building and Traversing Graphs" markers: "74": "Recap and set the stage for the day" "172": "handmade_sort.cpp: Briefly look through what BuildSpriteGraph() does" "308": "Blackboard: Graph sort" "515": "Blackboard: Subgraphs, and marking each node you touch" "578": "Blackboard: Cycles" "701": "Blackboard: The steps involved in doing this graph sort" "832": "handmade_sort.cpp: Reorganise our graph structs" "1002": "handmade_sort.cpp: Begin to implement BuildSpriteGraph() for real" "1313": "Blackboard: Traversing the edges from foremost to backmost" "1417": "handmade_sort.cpp: Continue implementing BuildSpriteGraph()" "1471": "handmade_sort.cpp: Introduce WalkSpriteGraph()" "1567": "handmade_sort.cpp: Introduce RecursiveFromToBack()" "1770": "handmade_sort.cpp: Introduce enum sprite_flag, in order to mark sprites as visited and drawn" "1927": "handmade_sort.cpp: Make BuildSpriteGraph() and RecursiveFromToBack() use those flags" "2054": "Blackboard: Note that we've done the graph sorting steps out of order" "2102": "handmade_sort.cpp: Introduce struct sprite_graph_walk in order to keep track of our location in the graph" "2357": "Consider how we'll need to proceed" "2438": "handmade_sort.cpp: Clean up compile errors" "2538": "handmade_sort.cpp: Make BuildSpriteGraph() and SortEntries() take a memory_arena" "2630": "Consider doing the sort in pieces that don't interfere with one another" "2879": "Blackboard: Treating the game sort data and the debug sort data separately" "3160": "win32_handmae.cpp: Consider issuing RenderCommands() and LinearizeClipRects() in two separate places" "3309": "handmade_sort.cpp: Prevent BuildSpriteGraph() from calling PushStruct()" "3353": "win32_handmade.cpp: Prevent Win32DisplayBufferInWindow() from calling SortEntries()" "3376": "Run the game and find that the entries aren't sorted but that we don't crash" "3386": "Q&A" "3470": "Did you discuss why you are using recursion and any concerns with stack overflows?" "3544": "Working with graphs can be difficult; do you have any techniques for debugging them other than observing screen renders, or is that mostly sufficient?" "3646": "Okay for real, did you address the possibility for intersecting sprites?" "3670": "When I code I use the mouse a lot. You seem to be using a lot of shortcuts to jump here and there. Can you tell more about your shortcuts? Thanks!" "3722": "Do you know the dev Garry Newman? If yes, what do you think about his work?" "3760": "sssmcgrath I stopped using Razer's drivers as soon as you needed an account" "3783": "What's that shirt?" "3840": "Wind it down" --- name: "day305" title: "Using Memory Arenas in the Platform Layer" markers: "31": "Recap and set the stage for the day" "122": "handmade_opengl.cpp: Consider making this whole file platform independent" "298": "handmade_platform.h: Consider moving platform_opengl_display_bitmap and platform_opengl_render_commands in from handmade_opengl.cpp" "430": "Consider (the downsides of) making all the platform layers include bindings and link the dll with opengl" "599": "win32_handmade.cpp: Make Win32DisplayBufferInWindow() call SortEntries(), and consider moving the sorting or the memory arena into the platform specific layer" "691": "Create handmade_memory.h and #include it handmade_shared.h" "1027": "Consider the concept of an overflow memory state" "1213": "win32_handmade.cpp: Make Win32DisplayBufferInWindow() take a memory_arena and create some temporarary_memory for SortEntries() and LinearizeClipRects() to use" "1440": "handmade_opengl.cpp: Make OpenGLRenderCommands() call GetSortedIndices()" "1503": "handmade_render.cpp: Make RenderCommandsToBitmap() call GetSortedIndices()" "1562": "handmade_platform.h: Introduce game_render_prep struct and make the necessary functions take it" "1904": "handmade_render.cpp: Introduce PrepForRender()" "1997": "4coder: Request a mode that automatically creates a boundary in the bottom-right corner" "2032": "win32_handmade.cpp: Stop WinMain() from dealing with the ClipMemory and make LinearizeClipRects() in handmade_render.cpp do it itself" "2137": "On the importance of good utility functionality" "2489": "Create handmade_render.h and stick the sprite structs in there" "2990": "Run the game and hit the assertion in OpenGLRenderCommands()" "3130": "handmade_render.cpp: Assert that OutIndex - OutIndexArray == InputNodeCount in WalkSpriteGraph(), and make SortEntries() traverse the nodes and write the indices of them" "3281": "Run the game and see that all of our stuff is flowing without crashing" "3315": "handmade_render.cpp: Make RecursiveFromToBack() correctly increment the OutIndex" "3349": "Run the game and hit the assertion in BuildSpriteGraph()" "3370": "handmade_render.cpp: Explain how RecursiveFromToBack() is working" "3510": "handmade_render_group.cpp: Make PushRenderElement_() clear Flags" "3582": "Run the game, confirm that our sort isn't working and consider how to make it work" "3763": "Q&A" "3872": "Line 31?" "3965": "Since no on-topic, off-topic: Will the final game be orthographic?" "4002": "When you're calculating pre-allocated buffer locations with offsets, do you find the pointer bugs that pop up sometimes difficult to track down, or is that kind of a non-issue when you do it often enough?" "4434": "Which system did you start programming on, way back in the previous millennium?" "4495": "I know there is debug code for how long functions take. Is there any debug code for how much of a memory arena is being used?" "4547": "Recollections of the Rainbow 100 and Turbo Pascal" "4846": "Did you program on the Amiga?" "4867": "Did it have Word Star key bindings? That's really the test" "4874": "Close down" --- name: "day306" title: "Debugging Graph-based Sort" markers: "11": "Recap and set the stage for the day" "100": "Run the game and see the current state" "231": ""Let's use the word "evolucent""" "246": "handmade_render_group.cpp: Make PushRenderElement_() take and set the ScreenArea" "301": "handmade_render_group.cpp: Make PushRect() set the ScreenArea" "414": "handmade_render_group.cpp: Make PushBitmap() set a provisional ScreenArea for the sprite" "490": "Blackboard: The ScreenArea for Regular vs Rotated Sprites" "711": "handmade_render_group.h: Add ScreenArea to render_group and make Clear() take it" "1023": "handmade_render_group.cpp: Make Perspective() set the ScreenArea" "1095": "Debugger: Run the game, crash in BuildSpriteGraph() and inspect the ScreenArea values" "1218": "handmade_render_group.cpp: Look through GetRenderEntityBasisP() and note that NearClipPlane is set so that 0 is clipped out" "1259": "Debugger: Inspect the values of B" "1308": "handmade_render_group.cpp: Assert in PushRenderElement_() that GetArea(ScreenArea) < 2000 * 2000" "1408": "handmade_math.h: Introduce GetArea()" "1476": "Debugger: Run the game and hit that assertion, then step out and see who called that function" "1573": "handmade_render_group.cpp: Comment out that assertion, run the game and look at the actual bug" "1588": "handmade_render.cpp: Reenable the PushStuct() call in SortEntries()" "1614": "Run the game and see that we're running incredibly slowly" "1647": "handmade_render.cpp: Make BuildSpriteGraph() and WalkSpriteGraph() a TIMED_FUNCTION" "1678": "build.bat: Switch to -O2" "1704": "Run the game and realise that we can't see the debug display because it isn't sorted correctly" "1746": "build.bat: Switch back to -Od" "1792": "Run the game and see that we're getting some pretty non sequitur results" "1846": "handmade.cpp: Switch back to the title sequence in order to see how the sorting routine performs on these" "1903": "Note that the drop shadow of the text is being sorted incorrectly" "2022": "handmade_cutscene.cpp: Try and scramble the order of the first scene's layers" "2062": "Run the game and see that the scene is now incorrectly sorted" "2125": "Debugger: Break into BuildSpriteGraph() and inspect the values for A and B" "2156": "handmade_render.cpp: Prevent BuildSpriteGraph() from comparing NodeIndexA with itself" "2211": "Debugger: Break into BuildSpriteGraph() and see that A and B are now different" "2330": "Debugger: Step through BuildSpriteGraph() and see if it behaves as expected" "2463": "Debugger: Step through WalkSpriteGraph() and RecursiveFromToBack() and see if they behave as expected" "2737": "Debugger: Step through OpenGLRenderCommands() and inspect the SortedIndices array" "2829": "handmade_cutscene.cpp: Make RenderLayeredScene() DebugTag the cutscene layers" "3034": "Debugger: Run the game, step through BuildSpriteGraph() and RecursiveFromToBack() and watch the DebugTag values" "3150": "handmade_cutscene.cpp: Revert the cutscene layers to their original order" "3175": "Debugger: Step through RecursiveFromToBack(), watch the DebugTag values and confirm that the code is doing what we think it is doing" "3267": "handmade_render.cpp: Look through how the sort_sprite_bound flows through the functions" "3410": "handmade_cutscene.cpp: Note the reason why the cutscene was sorting as it was" "3492": "handmade_world_mode.cpp: Make UpdateAndRenderWorld() only generate one screen and disable the Monstar" "3618": "handmade_world_mode.cpp: Prevent AddStandardRoom() from calling BeginGroundedEntity()" "3636": "Run the game and hit the Assert in OpenGLRenderCommands() because ClipRectCount == 0" "3699": "Debugger: Investigate how we ended up with no ClipRects" "3927": "handmade_render_group.cpp: Make BeginRenderGroup() rather than Perspective() take the PixelWidth and PixelHeight in order to compute the ScreenArea, and call PushClipRect()" "4166": "handmade_world_mode.cpp: Make AddStandardRoom() create one tile" "4197": "Run the game and see that our sort appears to handle our Y-sprites just fine, but that our Z-sprites are all messed" "4232": "Defer questions until Monday and end it now" --- name: "day307" title: "Visualizing Sort Groups" markers: "11": "A few words on the bonuses of programming on stream" "127": "Run the game and demo the bug" "160": "handmade_world_mode.cpp: Reenable the else clause in AddStandardRoom() to generate the rest of the room" "203": "handmade_render_group.cpp: Correct RectMinMax to RectMinDim in PushRect()" "274": "Run the game and see how the sprites are sorted with that typo having been corrected" "426": "build.bat: Toggle HANDMADE_INTERNAL on" "492": "Run the game and see the profiler being sorted improperly" "542": "Consider augmenting our ability to see how the sort is behaving" "707": "handmade_entity.cpp: Disable the volume highlighting and the PushRectOutline for the traversables" "772": "Run the game and note that the speed has increased, and that the trees are all now sorted properly" "874": "handmade_world_mode.cpp: Make AddStandardRoom() add a room above" "904": "Run the game and see that the sort is actually wrong" "935": "handmade_opengl.cpp: Make OpenGLRenderCommands() draw the sprite bounds" "1093": "handmade_render.h: Add Sprite_DebugBox to the sprite_flag enum" "1122": "handmade_opengl.cpp: Continue working on OpenGLRenderCommands()" "1165": "handmade_opengl.cpp: Introduce OpenGLDrawBoundsRecursive()" "1327": "handmade_opengl.cpp: Make OpenGLRenderCommands() draw each bound in a different colour" "1624": "Run the game and see that it does nothing" "1636": "handmade_opengl.cpp: Make OpenGLRenderCommands() call glDisable(GL_TEXTURE_2D) before the bounds drawing routine" "1677": "handmade_opengl.cpp: Make OpenGLDrawBoundsRecursive() draw a line between the centres of two sprite bounds" "1839": "handmade_opengl.cpp: Introduce OpenGLLineVertices()" "1913": "handmade_opengl.cpp: Make OpenGLDrawBoundsRecursive() call OpenGLLineVertices()" "1947": "Run the game and see our new debug visualisation" "2015": "handmade_world_mode.cpp: Disable the Clear() in UpdateAndRenderWorld() for now" "2031": "Run the game, see it without the Clear and consider how best to slipstream that Clear into the process" "2224": "handmade_opengl.cpp: Make OpenGLRenderCommands() call glClear() and consider leaving the Clear() off in UpdateAndRenderWorld()" "2242": "handmade_opengl.cpp: "Get our hideous pink on"" "2301": "handmade_platform.h: Add a ClearColor to the game_render_commands struct and change how the screen clearing works in general" "2506": "Run the game and see what happens now" "2566": "handmade_opengl.cpp: Enable OpenGLRenderCommands() to toggle drawing the sprite bounds" "2686": "Run the game and try toggling the sprite bounds" "2714": "handmade_world_mode.cpp: Make AddStandardRoom() draw multiple layers" "2754": "Run the game and see the state of our sorting" "2799": "Blackboard: Sort Error Sources" "2850": "Blackboard: Bugs" "2869": "Blackboard: Bad Comparison" "2936": "Blackboard: Graph Cycle Resolution" "3066": "Consider drawing graph cycles, and ways to resolve cycles" "3180": "Blackboard: Generation Tag" "3272": "Blackboard: Erasable Bit" "3333": "handmade_render.h: Add Sprite_Cycle to the sprite_flag enum" "3382": "handmade_render.cpp: Make RecursiveFromToBack() first set and later clear the Sprite_Cycle" "3434": ""You know it's been a bad day when you don't know where the ~ key is"" "3440": "handmade_render.h: Add HitCycle to the sprite_graph_walk struct" "3484": "handmade_render.cpp: Make WalkSpriteGraph() and RecursiveFromToBack() work in tandem with that HitCycle" "3574": "handmade_opengl.cpp: Make OpenGLRenderCommands() only draw the sprite bounds for sprites that cycle" "3620": "Run the game and see no cycles" "3659": "Q&A" "3685": "Wherefore art thou... Can't wait to watch that stream begins?" "3746": "Programming won't necessarily be in your life forever. I feel like you will eventually settle down and write fiction novels" "3760": "How do you decide when a problem is complex enough to need visualization?" "3951": "Is the build graph still O(n^2)?" "4071": "When can we download JACS Season 5?" "4095": "Wrap it up" --- name: "day308" title: "Debugging the Cycle Check" markers: "13": "Recap and set the stage for the day" "79": "Run the game and show where we left things" "126": "handmade_opengl.cpp: Make OpenGLRenderCommands() draw a black border around the render entries" "501": "Run the game and see what our outlines are telling us" "618": "handmade_opengl.cpp and handmade_render.cpp: Look through the collision group drawing routines and consider what could be wrong" "735": "handmade_render.cpp: Rename RecursiveFromToBack() to RecursiveFrontToBack()" "794": "handmade_render.cpp: Make RecursiveFrontToBack() set and check things in the correct order" "860": "Run the game, see the cycles in our sort graph and investigate them" "994": "handmade_world_mode.cpp: Make AddStandardRoom() only generate one room, run the game and see what happens with cycles" "1262": "handmade_opengl.cpp: Make OpenGLRenderCommands() draw collision groups lightly, then increase their alpha when they cycle" "1322": "Run the game and view the cycles" "1432": "Consider how we're doing the sorting in the first place" "1638": "Continue to investigate what's happening with the cycles" "1774": "handmade_render_group.cpp: Change where PushRectOutline() draws the four edge rectangles" "1863": "Blackboard: Drawing an outline out of non-intersecting rectangles" "2114": "Blackboard: What RectanglesIntersect() is currently doing" "2226": "handmade_render_group.cpp: Make PushRectOuline() add an epsilon into the equation" "2251": "Run the game, see that our outlines no longer cause a cycle, but that our hero still does" "2645": "handmade_debug.cpp: Make DEBUGEnd() draw one character, run the game and step through SortEntries" "2849": "handmade_render_group.cpp: Make GetBoundFor() use the SortBias" "2931": "Run the game and see that the debug text is now correctly sorted" "3067": "handmade_render.cpp: Look at IsInFrontOf()" "3247": "Blackboard: How IsInFrontOf() is working" "3330": "Run the game and illustrate the possibility that we may actually be in okay shape here" "3410": "handmade_world_mode.cpp: Toggle AddMonstar() and AddFamiliar() back on" "3482": "Q&A" "3545": "I couldn't drop that into The Witness, then. FailFish Really. Kappa?" "3566": "It looks like the torso sprite occasionally draws on top of the head sprite, e.g. going up stairs" "3601": "Blackboard: How the hero is constructed" "3678": "Does collision work between stairs and hero? Because body under and head above the stairs should not happen" "3849": "Do you anticipate similar (if not identical) graph sorting would be used for any other game purpose (other than sprite sort)?" "3940": "What language is this?" "4000": "What are a few pieces of advice you would give to a new programmer?" "4145": "What is your estimate time it will take for you to finish Handmade Hero? And how different is it from the original estimate? (I assume you are about halfway)" "4373": "Off-topic: At the start of the show, you said that every game programmer uses a dev setup similar to what we use: debug with Visual Studio, but code with a different editor. Why?" "4505": "Are you enjoying this project as a programming challenge or are your efforts mainly put into the teaching part of it?" "4632": "What do you think about unit testing and test driven development applied to C++ code? Is this technique really useful and worth trying?" "5202": "It's because you are the only programmer! When working in a team that will use your code, you need const" "5364": "I programmed in 100% const correct for 5 years. Never again" "5381": "Close it on out" --- name: "day309" title: "Grid Partitioning for Overlap Testing" markers: "9": "Recap and set the stage for the day" "113": "Run the game and see where we left off" "245": "handmade_entity.cpp: Toggle off the volume highlighting in UpdateAndRenderEntities()" "273": "Lose the hoodie" "291": "Run the game and consider putting good data into the sorting routine so that it can do stable sorts" "358": "Consider how to proceed" "453": "Determine to solve our n^2 problem" "596": "Blackboard: The problem with determining which sprites overlap" "743": "Blackboard: Grid Partitioning as a way to mitigate routines proportionate to n^2" "861": "Blackboard: Testing for overlap in one dimension" "1064": "Blackboard: How to do this bucketing, or spatial partitioning" "1208": "Blackboard: Breaking up each entity" "1247": "Blackboard: Creating a more hierarchical notion of what the space looks like" "1447": "Blackboard: Quadtree, KD Tree and BSP Tree" "1610": "Blackboard: Favouring a very simple grid bucketing scheme" "1788": "Run the game and consider how expensive the BuildSpriteGraph() is" "1930": "Start with something fairly stupid" "1945": "handmade_render.cpp: Introduce sort_grid_entry struct and make BuildSpriteGraph() record if a sprite occupies a grid square" "2278": "handmade_render.cpp: Consider some immediate possibilities for optimisation" "2399": "handmade_render.cpp: Consider making RecursiveFrontToBack() not create the edges of the graph" "2545": "handmade_render.cpp: Introduce GetGridSpan()" "2839": "Blackboard: Adding edges from the perspective of grid testing" "3035": "handmade_render.cpp: Make GetGridSpan() bin the incoming screen area versus the total screen area" "3218": "handmade_render.cpp: Make BuildSpriteGraph() compute the InvCellDim" "3384": "handmade_render.cpp: Make GetGridSpan() work a little differently" "3599": "Run the game and note that we are now bucketing" "3622": "Q&A" "3686": "Using the grid system, do you think that would be good to use for pixel perfect collision?" "3711": "Blackboard: Determining whether rectangles and then possibly pixels intersect" "3834": "Why not have the debug overlay render to a separate layer, and have it draw in the order submitted instead of wasting time sorting?" "3940": "I think a sort-free mode would work well with the cutscene as well" "4030": "Missed the stream again, why do you not use the summed rectangle of the hero sprites for draw sorting, and draw the individual parts in a set order?" "4105": "Something exciting happening over at Molly Rocket?" "4119": "Can using C programming optimize the game more than C++?" "4375": "RTTI" "4449": "Wind it down" --- name: "day310" title: "Finishing Sort Acceleration via Gridding" markers: "9": "Recap and set the stage for the day" "103": "win32_handmade.cpp: Toggle on GlobalShowSortGroups, run the game and view those graphs" "239": "handmade_render.cpp: Accelerate BuildSpriteGraph() by making it loop through everything in each grid cell when we do an insertion" "525": "Run the game and see how our ACCELERATED_SPRITE_SORT fares" "608": "handmade_render.h: Increase the resolution of the SORT_GRID, run the game and see how this affects the speed of BuildSpriteGraph()" "720": "build.bat: Temporarily switch to -O2, run the game and see that this drastically improves the speed of BuildSpriteGraph()" "775": "handmade_render.cpp: Pass NoClear() to the PushStruct() calls in BuildSpriteGraph()" "914": "Run the game and consider the possibility that we may be checking things multiple times" "1049": "Blackboard: How the grid partitioning makes us check things multiple times" "1159": "Blackboard: Our two options for avoiding this" "1234": "Consider how to tag the sprites as having been touched" "1373": "handmade_render.h: Move the existing flags in the sprite_flag enum into the high bits and add Sprite_IndexMask" "1511": "handmade_render.cpp: Make BuildSpriteGraph() & the B->Flags with Sprite_IndexMask" "1624": "Run the game and see that the cycles are much rarer" "1654": "Explain what just happened" "1752": "win32_handmade.cpp: Toggle GlobalShowSortGroups off, run the game and see how our changes have affected the speed of BuildSpriteGraph()" "1886": "Blackboard: Manual Sort Override" "2248": "Blackboard: Edges Added Manually" "2394": "Blackboard: Specifying Sprites to be Drawn as a Group" "2560": "handmade_render.h: Consider adding a Count to the sort_sprite_bound struct" "2672": "handmade_render_group.h: Try adding a NextOffset to the render_group_entry_header struct" "2798": "handmade_opengl.cpp: Make OpenGLRenderCommands() daisy-chain the render entries" "2997": "Run the game, demo a sorting situation we need to resolve and consider how to resolve it" "3180": "Blackboard: Why put the daisy-chaining into the actual sorting system" "3321": "handmade_render_group.cpp: Provisionally make PushRenderElement_() only sort a NewElement, otherwise merge the Existing entry" "3683": "Compile and run properly" "3694": "Q&A" "3727": "Thanks to the grid partitioning, do we now have a convenient way of doing the graph sort in SIMD, possibly processing four grid squares, or four sprites within a square, at once? Or is it not quite that simple?" "3938": "With regards to the flags and the order checking, if you are &ing the flags with the id, to test if you have seen it before, what happens when another item does the same check and &s it with the same (changed) unit? Doesn't that make the result different to the check flags & mask = id for the new item? Did I miss something (or did you & the flags with the mask before you set the id to clear it (the old id) first?" "4019": "Blackboard: How the Flags and the Sprite_IndexMask is working" "4177": "handmade_render.cpp: Streamline BuildSpriteGraph() a touch" "4419": "Will we ever do any network programming on Handmade Hero (i.e. multiplayer)?" "4448": "I love how you said "we don't want to solve this with hacks" for a particular sorting condition. Do you think the engine should cover most / all boundary conditions or is there room for "boundary hacks" in certain / extreme circumstances?" "4493": "Blackboard: On not having the necessary information to do a correct sort in 2D" "4665": "Close down" --- name: "day311" title: "Allowing Manual Sorting" markers: "10": "Recap and set the stage for the day" "268": "Plan to provide the ability to sort a collection of sprites" "338": "Blackboard: Our options for sorting a collection of sprites" "672": "Run the game and see our current situation" "738": "handmade_render_group.cpp: Remove NewElement from PushRenderElement_(), and introduce the notion of a writeback for the SortKey which overwrites a previously written SortKey with new information" "973": "handmade_render_group.cpp: Consider making PushBitmap() return something for PushRenderElement_() to take and modify" "1051": "handmade_entity.cpp: Make UpdateAndRenderEntities() call BeginAggregateSortKey() and EndAggregateSortKey() which marks which entities share a SortKey" "1382": "handmade_render_group.cpp: Implement BeginAggregateSortKey() and EndAggregateSortKey()" "1825": "handmade_render_group.cpp: Enable PushRenderElement_() to correctly set the AggregateBound for Y- and Z-sprites" "1910": "handmade_render.cpp: Introduce IsYSprite()" "2178": "Run the game and see that it actually looks somewhat workable" "2255": "handmade_render_group.h: Remove the daisy-chaining from the render_group_entry_header struct" "2392": "Run the game and consider the question of what order we put the hero sprites in" "2411": "handmade_world_mode.cpp: Reorder the AddPiece() calls in AddPlayer()" "2444": "handmade_world_mode.cpp: Stop those AddPiece() calls from taking such tweaky values" "2556": "Consider how to articulate the intention that one sprite (e.g. the head) must always draw in front of another (e.g. the aggregated body)" "2995": "Blackboard: Manual Edge Specification" "3228": "Q&A" "3378": "How do I get insobot to ask a question?" "3414": ""insobot is kind of a national treasure"" "3418": "Close it down" --- name: "day312" title: "Cross-entity Manual Sorting" markers: "8": "Recap and set the stage for the day with an embarassing confession" "95": "Run the game and assess our current situation" "286": "Blackboard: Manual Edge Specification" "422": "handmade_entity.cpp: Make UpdateAndRenderEntities() only call BeginAggregateSortKey() if the PieceCount is > 1" "475": "Consider how to articulate the intention that one sprite (e.g. the head) must always draw in front of another (e.g. the aggregated body)" "635": "handmade_entity.h: Add ManualSortInFrontOf and ManualSortKey to the entity struct" "677": "handmade_brain.cpp: Make ExecuteBrain() set those values when a Head and Body are linked" "910": "handmade_brain.cpp: Enable ExecuteBrain() to talk to the RenderGroup" "981": "handmade_entity.cpp: Consider how to specify the render order in UpdateAndRenderEntities()" "1182": "handmade_render_group.cpp: Consider making BuildSpriteGraph() add some additional edges that force sorts" "1298": "Consider simplifying things" "1386": "Blackboard: Putting something into the SortKey to tag it as AlwaysInFrontOf or AlwaysBehind" "1425": "handmade_render.h: Add AlwaysInFrontOf and AlwaysBehind to the sort_sprite_bound struct" "1473": "handmade_render.cpp: Make IsInFrontOf() check if sprite_bound A is AlwaysInFrontOf or AlwaysBehind B, to save having to manually specify edges" "1659": "handmade_platform.h: Add LastUsedManualSortKey to the game_render_commands struct" "1675": "handmade_render_group.cpp: Introduce ReserveSortKey()" "1845": "handmade_entity.cpp: Make UpdateAndRenderEntities() set AlwaysInFrontOf and AlwaysBehind" "1926": "handmade_render.h: Introduce manual_sort_key struct" "1988": "handmade_render_group.cpp: Erase ComputeSortKey() and make GetBoundFor() copy the ObjectTransform.ManualSort to SpriteBound.Manual" "2137": "handmade_platform.h: Move manual_sort_key in from handmade_render.h with a mini-rant on the language" "2206": "Run the game and see how we're doing" "2242": "Debugger: Break into ExecuteBrain() and see if we're setting the SortKey" "2351": "handmade_entity.cpp: Add a BreakHere in UpdateAndRenderEntities() when an EntityTransform is not AlwaysInFrontOf or AlwaysBehind" "2407": "Debugger: Break in there and inspect the values" "2565": "handmade_render.cp: Correct a typo in IsInFrontOf()" "2584": "Run the game and see that that wasn't our only bug" "2595": "handmade_render.cpp: Make IsInFrontOf() check AlwaysInFrontOf and AlwaysBehind separately and correctly" "2881": "Run the game and see that we're in a better situation, but not quite perfect" "3049": "Toggle on GlobalShowSortGroups and identify that, when the sorting is incorrect, we have a cycle" "3238": ""Thank you, Mr Cycle Detection"" "3255": "Q&A" "3295": "Perhaps breaking the cycle on the in-front / behind pair?" "3409": "Will there ever be a case when the character's facing direction will change what we want for the sort order? I can think of a possible case if the characters had arms. Does the current method take these cases into account?" "3454": "Looking forward to rewatching that simplification from early on. I don't think I quite followed that live" "3521": "I'm the communications director at a game development studio in Montreal. I just found your stream minutes ago and it's very fascinating. Your trailer seems to convey the idea that a game is "better" if it's entirely handmade, from scratch. Do you feel a game can't be made with as much "love" if it uses a premade engine as opposed to one that's made entirely from scratch? Do you not feel like reinventing the wheel may be a waste of time?" "3572": "On the amount of love involved in making games whether from scratch or using a pre-made engine" "3776": "On reinventing the wheel, and the educational responsibility of Handmade Hero" "4072": "On the assumption that someone made a wheel" "4129": "Blackboard: Where the game industry is at in terms of inventing the wheel" "4255": "There is no wheel" "4552": "On love and money" "4594": ""Your goal has to be that the reason you want money is to make games, not the reason you make games is to make money"" "4743": "Close up shop" --- name: "day313" title: "Returning to Work on Z Layers" markers: "11": "Recap and set the stage for the day" "128": "handmade_world_mode.cpp: Make AddStandardRoom() generate multiple layers, run the game and see how wrong the sorting is" "204": "A few words of encouragement on exploratory programming and embracing the forward flow of the architecture" "336": "handmade_entity.cpp: Make UpdateAndRenderEntities() work as it did before the work on the sorting, run the game and see how it looks" "517": "Blackboard: Z Slices and Two Separate Conceptualisations of What it Means to be Up" "689": "Blackboard: Layered Alpha Blending" "1077": "Blackboard: Solving this Problem" "1174": "Blackboard: Render Buffers" "1292": "Blackboard: Back of the envelope calculation on the potential Graphics Memory available to us" "1453": "Blackboard: Back of the envelope calculation on the potential Memory Bandwidth available to us" "1761": "Consider how to proceed" "1818": "handmade_entity.cpp: Introduce a TestAlpha in UpdateAndRenderEntities()" "2041": "Run the game and see what happens" "2086": "Debugger: Break into UpdateAndRenderEntities() and inspect the fade values" "2405": "handmade_entity.cpp: Tweak the FadeTopEndZ and FadeTopStartZ values in UpdateAndRenderEntities(), and again break into it" "2547": "handmade_opengl.cpp: Pass Entry->PremulColor.a to the rectangle drawing glColor4f() call in OpenGLRenderCommands()" "2629": ""So I'm going to go work this out on the blackboard and figure out if I'm just... uh... on crack"" "2714": "handmade_entity.cpp: Subtract WorldMode->CameraOffset.z from the CameraRelativeGroundZ computation in UpdateAndRenderEntities()" "2742": "Run the game and see that we're fine again" "2820": "Blackboard: What RecanonicalizeCoord is doing" "2971": "Blackboard: Offsetting Z" "3061": "handmade_world_mode.cpp: Make ChunkPositionFromTilePosition() Offset the entities' Z downwards" "3192": "handmade_world_mode.cpp: Make ChunkPositionFromTilePosition() compute TileDepthInMeters differently" "3260": "Debugger: Break into ChunkPositionFromTilePosition() and inspect the offset values" "3458": "Debugger: Break into ConvertToLayerRelative() and inspect the Z values" "3590": "handmade_entity.cpp: Provisionally compute the relative layer we want for the entities" "3726": "Q&A" "3827": "Um. Because undefined behavior?" "3870": "What keyboard do you have?" "3940": ""Like putting your finger in a cloud"" "3960": "Do you expect that the final game will contain enough sprites to warrant using a texture atlas to reduce the number of texture binds per frame?" "4113": "I don't understand why the "base" Z value of each floor would be negative, it seems really contrived. It seems very logical to me to have 0 as as the "bottom". Maybe it has to do with rendering? I have not followed the latest shows" "4190": "Blackboard: Canonical Point for a Chunk" "4402": "Wrap it up" --- name: "day314" title: "Breaking Sprites into Layers" markers: "43": "Recap and set the stage for the day" "181": "Run the game and see where we're at" "320": "handmade_entity.cpp: Stop UpdateAndRenderEntities() from calling ConvertToLayerRelative() and instead calculate the RelativeLayer as worked out yesterday" "488": "handmade_entity.cpp: Make UpdateAndRenderEntities() get a WorldPos from MapIntoChunkSpace() in order to compute that RelativeLayer" "629": "Run the game and see that we're in much better shape" "662": "Consider introducing a concept in the render of the layer Z and the actual Z value" "764": "handmade_render.h: Add ChunkZ to the sprite_bound struct" "794": "handmade_render.cpp: Make IsInFrontOf() test that ChunkZ" "907": "handmade_render_group.h: Add ChunkZ to the object_transform struct" "940": "handmade_render_group.cpp: Make GetBoundFor() set the ChunkZ" "964": "Run the game and see that that doesn't affect anything" "981": "handmade_entity.cpp: Make UpdateAndRenderEntities() set that ChunkZ" "1003": "See how that affects the sort" "1101": "handmade_entity.cpp: Make UpdateAndRenderEntities() expand the bounds of the traversables to draw them like actual tiles" "1174": "Run the game and consider our cycling situation" "1252": "handmade_render.cpp: Shrink the sizes passed to the RectanglesIntersect() call in BuildSpriteGraph()" "1323": "handmade_debug.cpp: Make DEBUGStart() set the ChunkZ for the debug elements" "1393": "Run the game and toggle on the debug groups" "1495": "Consider how to leverage the layer data in the renderer" "1691": "handmade_entity.cpp: Simplify UpdateAndRenderEntities() so that it only knows about the alpha and the fog levels" "1945": "handmade_entity.cpp: Turn off the Alpha" "2015": "handmade_render_group.cpp: Make StoreColor() take a pointer to an object_transform and change all other functions to take a pointer to it" "2443": ""In theory this is a computer, yes?"" "2468": "handmade_entity.cpp: Make UpdateAndRenderEntities() set the Color and tColor for the top layer and the far fog" "2580": "Run the game, break into UpdateAndRenderEntities() and inspect the EntityTransform values" "2637": "handmade_entity.cpp: Make UpdateAndRenderEntities() reverse the TestAlpha computation" "2680": "handmade_world_mode.cpp: Make AddStandardRoom() generate multiple layers of rooms" "2700": "Run the game, see how those layers of rooms look and consult the profiler" "2739": "build.bat: Switch to -O2, run the game and consult the profiler again" "2776": ""Oh my god! Why are there so many heads following me?"" "2921": "Consider always rendering everyone with the ChunkZ they started with" "3034": "Blackboard: Sort Barriers" "3182": "handmade_render.h: #define SPRITE_BARRIER_OFFSET_VALUE" "3237": "handmade_render.cpp: Make BuildSpriteGraph() take and return NodeIndexA, which SortEntries() will pass to it"