[video output=day631 member=cmuratori stream_platform=twitch stream_username=handmade_hero  project=code title="Revisiting Collision" vod_platform=youtube id=kT9vWvBQA_8 annotator=Miblo]
[0:00][Recap and set the stage for the day][:speech]
[1:31][Enjoy the door switch tiles and determine to explore :combat][:run]
[4:54][Start with asymmetric :combat, with enemies floating and the player tile-bound][:movement :research]
[8:18][Introduce SingleEnemyPattern][:"entity system" :movement]
[12:36][See no familiar][:"entity system" :movement :run]
[13:09][Make CreateDungeon() call AddPattern() with our SingleEnemyPattern][:"entity system" :movement :"procedural generation"]
[14:20][We have a familiar][:"entity system" :movement :run]
[14:42][Reacquaint ourselves with ExecuteBrain()][:"entity system" :movement :research]
[16:37][Force ExecuteBrain() to run the "!Blocked" path][:"entity system" :movement]
[17:03][Our familiar remains stationary][:"entity system" :movement :run]
[17:31][Compile in -Od]
[18:11][Step in to ExecuteBrain()][:"entity system" :movement :run]
[19:52][Reacquaint ourselves with the :movement code in the :"entity system"][:research]
[21:52][Implement the MovementMode_Floating case in UpdateAndRenderEntities()][:"entity system" :movement]
[23:17][Our familiar now moves][:"entity system" :movement :run]
[23:45][Our familiars are subject to :collision volumes][:"entity system" :movement :run]
[24:55][Make ExecuteBrain() conditionally run the "!Blocked" path][:"entity system" :movement]
[25:14][Familiars can still float and interact with us through walls][:collision :"entity system" :movement :run]
[25:29][Reacquaint ourselves with the "Blocked" code in ExecuteBrain()][:collision :"entity system" :movement :research]
[28:52][Make UpdateAndRenderEntities() draw the :collision volumes][:"debug visualisation" :"entity system" :movement]
[29:21][Our walls have :collision volumes][:"debug visualisation" :"entity system" :movement :run]
[29:42][Make ExecuteBrain() set MovementMode_Floating for the familiar][:"entity system" :movement]
[30:03][Our familiar follows us again][:"entity system" :movement :run]
[30:21][Make SingleEnemyPattern add a :collision volume][:"entity system" :movement]
[30:48][Our familiar has a :collision volume][:"entity system" :movement :run]
[30:55][Increase the :collision volume dimensions from 0.75³ to 1.25³ in SingleEnemyPattern][:"entity system" :movement]
[31:11][Check our familiar's :collision volume][:"entity system" :movement :run]
[31:13][Decrease the :collision volume dimensions from 1.25³ to 1³ in SingleEnemyPattern][:"entity system" :movement]
[31:18][Our familiars fail to collide][:collision :"entity system" :movement :run]
[31:40][Make SingleEnemyPattern set the EntityFlag_Collides][:collision :"entity system" :movement]
[32:10][Our familiars can still float through walls][:collision :"entity system" :movement :run]
[32:34][Reacquaint ourselves with EntityFlag_Collides][:collision :"entity system" :movement :research]
[33:41][Let CanCollide() ignore the EntityFlag_Collides][:collision :"entity system" :movement]
[33:54][Our familiar collides with the doorway][:collision :"entity system" :movement :run]
[34:17][Make SingleEnemyPattern elevate the :collision volume off the ground][:"entity system" :movement]
[34:32][Our familiar still collides with the doorway][:collision :"entity system" :movement :run]
[35:22][Remove EntityFlag_Collides][:collision :"entity system" :movement]
[37:12][Our familiar may be colliding with the room boundary][:collision :"entity system" :movement :run]
[38:10][Replace the EntityFlag_Collides with :collision responses, starting with SpeculativeCollide() ignoring room boundary collisions][:"entity system" :movement]
[42:30][Our familiars collide, but can lock][:collision :"entity system" :movement :run]
[43:35][@hexadecimalinteger]["We can see this dude grinding against the wall, which is nice." -Casey, 2021][:collision :movement]
[43:53][Determine to change the glove :movement scheme from a "generalised coordinates" to a "Lagrangian" simulation system][:collision :physics :run]
[48:46][Glove management example: Getting caught on doors][:collision :gameplay :movement :physics :run]
[50:06][Determine to replace the glove's kinematic :movement with an active management system][:collision :combat :gameplay :physics :run]
[52:56][Make AddPlayer() set the Glove's MovementMode to Floating][:"entity system" :movement]
[53:29][Our glove is still controllable][:"entity system" :movement :run]
[53:50][Introduce PDC() – proportional derivative controller – for ExecuteBrainHero() to use on the glove[ref
    site=Wikipedia
    page="PID controller"
    url=https://en.wikipedia.org/wiki/PID_controller]][:"entity system" :movement]
[58:27][Our glove follows us][:"entity system" :movement :run]
[58:48][Make ExecuteBrainHero() stiffen the glove's spring][:"entity system" :"hot reloading" :movement :programming :run]
[1:00:09][Our glove remains close to the hero][:"entity system" :movement :run]
[1:00:56][Enable ExecuteBrainHero() to throw simulated punches][:combat :"entity system" :movement]
[1:05:07][Throw punches][:combat :"entity system" :movement :run]
[1:06:08][Increase GloveFloatHeight from 0.25 to 0.5 in ExecuteBrainHero()][:combat :"entity system" :movement]
[1:06:21][Our glove still skates along the ground, and punches are too slack][:combat :"entity system" :movement :run]
[1:07:24][Punch speed-based damage][:combat :"entity system" :movement :run]
[1:08:24][Tighten up our glove spring in ExecuteBrainHero()][:combat :"entity system" :movement]
[1:08:38][Our glove still feels sticky][:combat :"entity system" :movement :run]
[1:09:23][Further tighten up our glove spring in ExecuteBrainHero()][:combat :"entity system" :movement]
[1:09:29][Try throwing punches][:combat :"entity system" :movement :run]
[1:10:09][Look into MovementMode_Floating][:"entity system" :movement :research]
[1:11:27][Our glove :movement behaves oddly][:"entity system" :run]
[1:11:37][Make ExecuteBrainHero() match the Glove's FacingDirection to the body's][:"entity system"]
[1:11:52][Our glove :movement feels odd][:"entity system" :run]
[1:12:39][Reacquaint ourselves with MoveEntity() and the entity DistanceRemaining][:"entity system" :movement :research]
[1:15:34][Begin to rewrite MoveEntity() without DistanceRemaining][:"entity system" :movement]
[1:21:36][Our problems: 1) Determining how far we can go in a particular direction; 2) Sliding against surfaces][:collision :movement :research]
[1:24:09][Continue to rewrite MoveEntity(), determining the closest point to move to][:"entity system" :movement]
[1:27:03][Set up the lightboard][:admin]
[1:27:13][:afk]
[1:29:57][Switch the scene][:admin]
[1:30:15][Check the sound levels][:admin]
[1:30:40][Closest point :movement and :collision detection][:blackboard]
[1:31:29][Our problem: Gliding along :collision volumes][:blackboard :movement]
[1:35:21][Deterministic gliding :collision system structure][:blackboard :movement]
[1:38:58][Gliding :collision as a :pathfinding problem][:blackboard :movement]
[1:41:59][The Witness's localised grid for gliding :collision][:blackboard :movement]
[1:44:00][Gliding :collision as a :pathfinding problem (cont.)][:blackboard :movement]
[1:49:19][Legal path segment picking][:blackboard :collision :movement :pathfinding]
[1:52:58][Overlap testing][:blackboard :collision :movement :pathfinding]
[1:56:42][Window cleaning, dreaming of a self-erasing board][:admin :blackboard]
[1:58:53][Hemispherical gliding :collision][:blackboard :movement :pathfinding]
[2:02:57][Small-scale localised grid for gliding :collision][:blackboard :movement]
[2:06:06][Legal position picking, subdividing cells by nine][:blackboard :collision :movement]
[2:11:03][Boundary-avoiding subdivision][:blackboard :collision :movement]
[2:12:43][Data requirements: "Closest to Dest" and "Connectivity" (Exits)][:blackboard :collision :movement]
[2:18:52][Subdividing by changing the :collision sphere's enlargement radius][:blackboard :movement]
[2:21:06][Determine to sleep on our :collision][:blackboard :movement]
[2:21:30][We're out of time][:speech]
[2:22:18][Q&A][:speech]
[2:22:34][@mtsmox][Q: Wouldn't this allow longer paths than the original, since you could still reach the goal while going a longer route?][:collision :movement]
[2:24:03][@alizarinc][Q: Has there been any advancement on the 4-simplex case of GJK? Been reading your blog[ref
    site="Casey's Tech Stuff"
    page="Implementing GJK (2006)"
    url=https://caseymuratori.com/blog_0003] about this topic][:collision :movement]
[2:24:33][@volcanicpopsicle][Q: Why not just move the character to the closest legal point of the desired end point?][:collision :movement]
[2:25:04][@technicbeam][Q: I've never used a lightboard, so take this with a grain of salt, but if the edges were sealed so water couldn't get there, could you just spray and squeegee it?]
[2:25:56][@volcanicpopsicle][Q: I mean not the closest point on the path but closest point in the half sphere. But, yeah, I guess the problem is finding the closest point?][:collision :movement]
[2:26:56][@volcanicpopsicle][That's probably a stupid question][:collision :movement]
[2:28:24][@puuhs_mama][If there is a frame stutter, then the small :movement becomes really large?][:collision]
[2:29:50][@dmitriykubyshkin][@handmade_hero For the lightboard there are already large transparent TVs, so the only question is price and pen tracking which is a solved problem]
[2:31:57][@nairou2][Q: At any point in your development as a programmer, have you ever dealt with pointer aversion? I tend to avoid storing pointers, using array index lookups every time instead, to avoid the possibility of a bad / null pointer. I feel like I'm limiting myself by doing this, but it also feels valid. Have you dealt with this, and have any advice / opinion on it?][:language]
[2:37:25][@centhusiast][Q: Is it possible to replace the entire web stack by C? I mean both back-end and front-end][:language]
[2:38:03][@exp_ix][Q: When your 0th slot is reserved, do your loops start from 1 or 0 then?][:language]
[2:38:51][@stanislav_ts][What would you then say to the idea that pointers can be be better because the compiler knows to prefetch the targets of pointers. This is not the case with indices as there are no "pointy" semantics there that the compiler understands][:language]
[2:40:59][@filiadelski][@handmade_hero You better post pictures of that to #food or I will find you]
[2:41:17][@stanislav_ts][I cannot give an example. It is just somethings that I've heard other people talk about when they give counter arguments for using indices][:language]
[2:42:00][Prefetching pointer targets[ref
    site="Compiler Explorer"
    url=https://godbolt.org]][:language :research]
[2:49:23][@filiadelski][@handmade_hero Pass in -Os for small code?]
[2:49:45][@mitchty][__builtin_prefetch()[ref
    site=GCC
    page="6.59 Other Built-in Functions Provided by GCC"
    url=https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html] is the way to hint, but still gotta test it][:language]
[2:50:53][@mitchty][It's __builtin_prefetch(&location, optional)][:language]
[2:51:45][@mitchty][Yep, it's not in the optimizer][:language]
[2:51:59][GCC vs Clang loop unrolling[ref
    site="Compiler Explorer"
    url=https://godbolt.org]][:language :research]
[2:59:24][@mitchty][Try -Oz in clang][:language]
[2:59:36][GCC vs Clang loop unrolling (cont.)[ref
    site="Compiler Explorer"
    url=https://godbolt.org]][:language :research]
[3:01:19][Gotta go][:speech]
[/video]
