Try that. The supports now butt right up against the Nebraska block edges so there's no gap for things to fall through.
Ah right -- the problem is the opposite of what I've been fighting. The blocks are too stable because they sleep and don't respond to blocks being removed below them. They just float in place.
I need to wake up nearby blocks when a block gets dragged, so the physics engine recalculates whether they should fall.
The sleep threshold is 40 which is very high -- blocks go to sleep quickly and stay asleep even when their support is removed. I'll wake all blocks whenever a drag starts.
Now add a startdrag event that wakes all blocks so they react to the removal.
Good, we have Sleeping imported. Now I need to add an event listener. Let me find where the mouse constraint is set up.
That should fix it. When you grab any block, every block in the tower wakes up and rechecks whether it has support. Pull a bottom block and the ones above should now fall.
Good. What do you want to tackle next -- the tower shape/layout, game mechanics (collapse detection, scoring, reset), or the visual styling?
Got it, removing the Nebraska block.
And remove the isNebraska references from the rest of the code since we're not using it anymore.
Done. Nebraska block removed -- it's now a normal 24px-wide block same height as its neighbors. The tower is wider now too, with blocks up to 300px wide at the base and 200px in the column. Refresh and see how it looks.
That's not a real font file. Let me find the right URL.
Done. Want me to commit what we have so far?
Done. Files are now at /Users/andrew/code/nesbitt.io/xkcd-2347/. Want me to switch my working directory there and commit?
Committed as f6b3ac7 on master. I'll work from /Users/andrew/code/nesbitt.io/xkcd-2347/ going forward. What's next?
Done. Removed the score display, overlay, and rebuild button from the HTML.
Good idea. Let me think through the algorithm:
The key constraint is that every block must sit on top of something from the row below -- no overhangs beyond the previous row's edges or it'll topple.
Let me build this.
Refresh and try it. Each page load gives a new random tower. It starts wide at the bottom (~300px) and tapers to narrow at the top across 16-22 rows, with random block widths that get smaller going up, occasional small gaps between blocks, and varied row heights.
Got it, skipping the font. I'll use a fallback and we can add the font later. Let me build everything now.
Changes:
Refresh a few times to see the variety.
15% chance any row becomes a single massive block spanning the full row width and 30-55px tall. These will be the big chunky slabs you see in the comic. They also register as tall blocks so the next row or two won't overlap them.
That's the comic zoomed in. Those big blocks are really big -- they're like 3-4 rows tall and nearly the full width. And notice how the smaller blocks sit on top of and around them. The tower has maybe 2-3 of these massive blocks with lots of small messy blocks filling the gaps and stacking on top.
Let me bump up the big block frequency and make them even bigger.
Big blocks are now 50-90px tall (was 30-55) and 70-100% of the row width. 20% chance per row. They'll tower over the smaller 12-28px blocks around them.
That's looking much better. The big blocks are showing up and there's good variety. I can see a couple things to improve:
Want me to adjust the taper curve to be less pyramidal, or is there something else you want to change first?
That one's got a big block that's way too wide relative to the rows below it -- overhanging off the right side. The big blocks shouldn't be wider than the row width at that level.
Also the taper is still very pyramidal. Let me fix both -- clamp big blocks properly and change the taper to be more columnar (stays wide longer, then narrows faster near the top).
Now clamp the big blocks so they can't exceed the row width:
Two fixes: the taper is now columnar (stays wide for the bottom 60%, then drops off steeply), and big blocks are clamped to 65-95% of the current row width with their offset limited so they can't overhang.
I'll add random width jitter per row and a chance for long thin cantilever blocks that stick out past the row edges.
Now add cantilever blocks. I'll put them after each row's normal blocks are placed:
Changes:
That's looking much more like the comic. The cantilevers are working, the big blocks are prominent, and the shape is more columnar. Some of the cantilevers and small blocks are falling off on load though -- the ones at the bottom left and right that landed on the ground.
The cantilever blocks are sticking out too far (only ~65% supported). Let me make them more like 75-80% supported so they balance better. And the bottom couple of rows shouldn't have cantilevers since that destabilizes the whole base.
Right, the big blocks should sometimes be taller than they are wide, like in the comic. Let me adjust.
Big blocks now: 50-85% of row width (narrower) and 60-120px tall (taller). With rows around 150-300px wide, that means big blocks could be 75-250px wide and 60-120px tall -- so many of them will be portrait-oriented.
The blocks are too heavy so gravity squishes them together during the initial physics frames. I'll reduce the density.
Quarter of the previous density. Should compress much less on load.
Now the big one -- the game logic.
Bumped friction from 0.9 to 1.0 and static friction from 2.0 to 3.0. Blocks should grip each other better now.
Ha, good. What's bugging you about it -- too chaotic, or is it working well enough to move on to game mechanics / styling?
The cantilevers and gaps are destabilizing things too much. Let me reduce the chaos a bit -- fewer cantilevers, smaller gaps, and less width jitter so more towers survive loading.
A few things are causing instability:
Yes -- Matter.js sleeping is exactly that. When all bodies have gone to sleep, nothing is moving. You can check it in the game loop:
Want me to add that as a settled/stable detection? Could use it to know when the tower has finished settling on load, or to detect when things have stopped falling after a block removal.
That's a great idea. Let me add settled detection and a random project name generator.
Let me test it in a browser to see how it looks.
Now add the settled detection in the game loop and draw the name:
Now draw the project name below the tower when settled:
Once the tower settles (all blocks sleeping), a random project name like "libcrypt-utils" or "node-parse.js" or "hyper-mux-fast" appears below the tower. Each reload generates a new tower and a new name.
Moved to top of canvas at 20px font.
Shows the name after either all blocks sleep or 5 seconds, whichever comes first.