riiiiiiiiiiiiiiiiiiiight i remember reading about this... thank you!
26.07.2025 02:57 โ ๐ 0 ๐ 0 ๐ฌ 0 ๐ 0@aaaa.sh.bsky.social
working with the garage door open!
riiiiiiiiiiiiiiiiiiiight i remember reading about this... thank you!
26.07.2025 02:57 โ ๐ 0 ๐ 0 ๐ฌ 0 ๐ 0javascript is a great game engine, actually
25.07.2025 23:18 โ ๐ 4 ๐ 0 ๐ฌ 1 ๐ 0the original source jsx code. const todos = [ { text: 'Play Donkey Kong Bananza', }, { text: 'Continue Playing Donkey Kong Bananza', }, { text: 'Banana', bold: true }, ]; const app = <div> <h1 style="color: green">Todos:</h1> {...todos.map(todo => <li style={todo.bold && "font-weight: bold"}> {todo.text} <button onclick={() => {li.remove()}}>Remove</button> </li>) } </div> document.getElementById('app').appendChild(app);
The produced webapp. HTML that reads as the following: Todos: Play Donkey Kong Bananza (button) Remove Continue Playing Donkey Kong Bananza (button) Remove Banana (button) Remove
The transpiled javascript code, pretty printed by the chromium debugger. const todos = [{ text: "Play Donkey Kong Bananza" }, { text: "Continue Playing Donkey Kong Bananza" }, { text: "Banana", bold: true }]; const app = ( () => { let div = document.createElement("div"); div.appendChild(( () => { let h1 = document.createElement("h1"); h1.setAttribute("style", "color: green"); h1.appendChild(document.createTextNode("Todos:")); return h1; } )()); div.append(...todos.map( (todo) => ( () => { let li = document.createElement("li"); li.setAttribute("style", todo.bold && "font-weight: bold"); li.append(todo.text); li.appendChild(( () => { let button = document.createElement("button"); button.addEventListener("click", () => { li.remove(); } ); button.appendChild(document.createTextNode("Remove")); return button; } )()); return li; } )())); return div; } )(); document.getElementById("app").appendChild(app);
interesting #webdev thing today: i love JSX syntax but i don't want to bundle a runtime, so I wrote a custom parser that transpiles jsx to native DOM calls. I wrote it as a vite plugin; only 138 lines of code! no error reporting, but otherwise feature rich, and zero (really zero!) overhead.
22.07.2025 22:58 โ ๐ 1 ๐ 0 ๐ฌ 0 ๐ 0google is experimenting on me and apparently the experiment is "how long can we serve nothing until she stops using google." not that long! i have things i want to know on the internet
19.07.2025 10:16 โ ๐ 0 ๐ 0 ๐ฌ 0 ๐ 0has google just stopped showing results for anyone else?
19.07.2025 10:16 โ ๐ 0 ๐ 0 ๐ฌ 1 ๐ 0Pass nil to clear the state from the previous call, which restores a state thatโs equivalent to the default values of an MTLDepthStencilDescriptor instanceโs properties.
failed assertion `Set Depth Stencil State Validation depthStencilState must not be nil.
Apple docs: "yeah totally, you can pass nil. it'll just autofill the data for you. no problem dude"
Apple validation layers: "what the fuck. why would you pass nil. what is wrong with you"
here's a video version of the GIF above that doesn't seem to want to cooperate (curse you ffmpeg!!) #coding
30.06.2025 04:18 โ ๐ 0 ๐ 0 ๐ฌ 0 ๐ 0booting the game with a URL and waiting for the script to load & run. the command: odin run . -debug -- -r "use https://aaaa.sh/creatures/scripts/ground.hmny" idk why this gif is so slow i swear it's not like this in the game
code that starts a network request using apple's URLSession API. platform_start_network_request :: proc( url: string, req: ^Platform_Network_Request, ) { url_path := NS.String.alloc()->initWithOdinString(url) nsurl := msgSend(^NS.URL, NS.URL, "URLWithString:", url_path) local_completion_handler := NS.Block.createLocal( user_data = rawptr(req), user_proc = transmute(proc "c" (rawptr))network_completion_handler, ) url_session_task := msgSend(^URLSessionDataTask, msgSend(^URLSession, URLSession, "sharedSession"), "dataTaskWithURL:completionHandler:", nsurl, local_completion_handler, ) msgSend(struct{}, url_session_task, "resume") }
some assembly i wrote for the scripting language stdlib. it blocks on a network request if the file URL starts with http: or https:.
the game's scripting language can now download files! you can import and run code, fetch html, or even read the weather. it uses a poll system & you basically have to roll your own poll loop (but there is one in the stdlib). internally, it uses the OS' networking tools (had to do some objc lol)
30.06.2025 04:16 โ ๐ 2 ๐ 0 ๐ฌ 1 ๐ 0creatures | Memory | 725 MB
Creatures | Memory | 117 MB
The game already ran on Apple devices via MoltenVK, so this was mostly a learning exercise. There are some benefits though. Avoiding MoltenVK reduces code size, and improves CPU & GPU performance as we get closer to the hardware. Most importantly, it saves a TON of memory.
Vulkan / MoltenVK | Metal
vertex_buffer = gpu_buf_writeable(Block_Vertex, MAX_BLOCK_VERTS, .Vertex) instance_buffer = gpu_buf_writeable(Boro_Instance, MAX_BOROS, .Vertex) boro_chunks_texture = gpu_img({CHUNKS_PER_BORO, MAX_BOROS, 1}, .R32_UInt, {.Sampled}, {.CPU_Writeable}) energy_texture = gpu_img({2048, 2048, 16}, .R8_UInt, {.Sampled}, {.CPU_Writeable}) samp = gpu_sampler() block_drawing_resource_arena = gpu_initialize_resources( &vertex_buffer.untyped, &instance_buffer.untyped, &boro_chunks_texture, &energy_texture) chunks_binding_set = gpu_binding_set( { .Fragment }, &chunks_binding_set_layout, { &boro_chunks_texture, &energy_texture, &samp }, ) block_vert_shader := gpu_shader("block_vert") block_frag_shader := gpu_shader("block_frag") block_render_layout = gpu_render_layout( color_attachments = { { format = gpu_surface_format(), load_op = .Clear, transition = .To_Surface, }, }, depth_attachment = GPU_Attachment_Description { format = depth_image.format, load_op = .Clear, }, ) block_drawing_pipeline = gpu_graphics_pipeline_with_layout( &block_render_layout, &blocks_binding_layout, block_vert_shader, block_frag_shader, { gpu_vertex_desc(Block_Vertex), gpu_instance_desc(Boro_Instance) }, depth_enabled = true, )
The rendering code is simple too: the API is built on my personal mental model of how a GPU works, with some hacks and caveats for the idiosyncrasies of specific backends.
here's a code sample so you can see how simple it is. virtually no overhead!!
Wrote a custom cross-platform GPU API for my game's engine, so now it can directly speak both Metal and Vulkan through the same rendering code. The new API is designed to be super low-overhead: it doesn't allocate memory or do any hidden work. Here's a (slightly boring...) demo! #gamedev #techart
26.06.2025 08:50 โ ๐ 8 ๐ 1 ๐ฌ 1 ๐ 0After 9 months, I'm cutting the raytracing-based voxel renderer for my game and going back to basic meshing. (I'll have to do a post-mortem on why raytracing was a horrible idea!!) Anyway, here's a visualization for some basic voxel meshing stuff #gamedev
13.06.2025 06:37 โ ๐ 9 ๐ 1 ๐ฌ 1 ๐ 0they'll do anything before they bring back skeuomorphism
10.06.2025 00:22 โ ๐ 0 ๐ 0 ๐ฌ 0 ๐ 0A git diff, with a comment saying "Chunks are 4x4x4, Boros are 32x32x32. These values are chosen carefully and woven into the game's code and algorithms. These are not for playing with." As is seen in the diff, the comment and the corresponding code has been played with.
me when i ignore my own comment
01.06.2025 21:02 โ ๐ 1 ๐ 0 ๐ฌ 0 ๐ 0he's a dog, and he plays basketball. so simple, and yet so deeply complex
16.05.2025 08:15 โ ๐ 0 ๐ 0 ๐ฌ 0 ๐ 0quick note: i've put a bunch of my game development screenshots & videos at aaaa.sh/creatures in case people want to take a look at what i've been working on without scrolling through here #gamedev
14.05.2025 05:27 โ ๐ 3 ๐ 1 ๐ฌ 0 ๐ 0In a badly designed book, the letters mill and stand like starving horses in a field. In a book designed by rote, they sit like stale bread and mutton on the page. In a well-made book, where designer, compositor and printer have all done their jobs, no matter how many thousands of lines and pages, the letters are live. They dance in their seats. Sometimes they rise and dance in the margins and aisles.
The word "form" can be surgically revised, instead of rewritten, to become the word "farm" or "firm" or "fort" or "fork" or "form", or with a little more trouble, to become the word "pineapple."
Narrow row houses flush with the street are found not only in urban slums but in the loveliest of the old Italian hill towns and Mediterranean villages. A page full of letters presents the same possibilities. It can lapse into a typographic slum, or grow into a model of architectural grace, skilled engineering and simple economy. Broad suburban lawns and wide typographical front yards can also be uninspiringly empty or welcoming and graceful. They can display real treasure, including the treasure of empty space, or they can be filled with souvenirs of wishful thinking. Neoclassical birdbaths and effigies of liveried slaves, stabled boys and faded pink flamingoes all have counterparts in the typographic world.
A comparison of different page sizes with musical intervals.
just finished reading "The Elements of Typographic Style" by Robert Bringhurst; it was one of the most well-written textbooks I've ever read! here are some of my favorite excerpts #design #typography
12.05.2025 10:06 โ ๐ 2 ๐ 0 ๐ฌ 0 ๐ 0man i really went from "yeah i think it would be fun to make video games" to "HOLY SHIT WHAT IS THE DIFFERENCE BETWEEN X PRIME AND X PRIME PRIME" real quick #gamedev
01.05.2025 19:25 โ ๐ 4 ๐ 1 ๐ฌ 1 ๐ 0also please note that calculating AABB-style boxes around each object is expensive in and of itself.
20.04.2025 06:11 โ ๐ 0 ๐ 0 ๐ฌ 0 ๐ 0I don't have a good solution for this yet. I think the ideal solution involves:
- Using marching cubes to conform a slightly high-poly mesh outside the object.
- Using mesh deformation to destroy it as much as possible while staying outside the inner voxel data.
But wanted to share. I am tired.
several voxel objects with well-constrained low-poly meshes. a stick figure thinking "wow these meshes are well fit to the voxel obejcts that they belong to!"
So the obvious move is to shrink the render boxes. But how do we find the right new shape? How can we take voxel data and constrain a low-poly mesh to it in an efficient way? The simplest way is to find the smallest AABB-style box, but that excludes shapes like slopes and arcs. (5/N) #gamedev
20.04.2025 06:02 โ ๐ 4 ๐ 1 ๐ฌ 2 ๐ 0a very messy render box with 5 objects in it. text, which reads "each one of these objects has their own render box that is individually ray-traced in shader code." a stick figure is looking at it thinking "uh oh."
When we spawn multiple objects, each one gets its own mesh. The is fine on its own, the problem is that the minimum mesh size is 32x32x32, so we end up raytracing shaders all over empty space for smaller objects. Many pixels get ray-traced N times, where N is the number of objects. (4/N) #gamedev
20.04.2025 06:02 โ ๐ 4 ๐ 1 ๐ฌ 1 ๐ 0a drawing, a box labeled "REAL MESH (SENT TO GPU") around a big black box that encases a brown blob of blocks labeled "THIS IS THE SHAPE WE RENDER AND DRAW." Someone standing outside of the box labeled "view ray in rasterizer". They are sending out a ray from their eyes that turns green inside of the black box, the ray is labeled "view ray simulated in shader."
this is because each object is actually rendered as a cube. DDA is performed to ray trace 'inside' of the cube, which is how we get the actual shapes. here's a diagram and a debug visual for illustration. (3/N) #gamedev
20.04.2025 06:02 โ ๐ 4 ๐ 1 ๐ฌ 1 ๐ 0here's profiling capture for three frames, the middle one is a complete game tick. you can see that green bit in the middle, which is object creation. the tan stuff to the left (labeled '163') is collision code, and the black bars *everywhere* is voxel rendering. (2/N) #gamedev
20.04.2025 06:02 โ ๐ 3 ๐ 1 ๐ฌ 1 ๐ 0found a problem with my game today :) i wanted to stress-test the collision detection & gravity routines by spawning a ton of objects, turns out the bottleneck is rendering! each object caries with it a huge amount of rendering overhead, so the game slows to a crawl... (-ฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅแท_-ฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅฬฅแท ) (1/N) #gamedev
20.04.2025 06:02 โ ๐ 4 ๐ 1 ๐ฌ 1 ๐ 0i often find myself writing tiny visualizers for chunk metadata, so i added a really simple debug menu that gives me all the info i need. it's also a good test of keyboard navigation support for my immgui system. #gamedev
14.04.2025 01:06 โ ๐ 7 ๐ 1 ๐ฌ 0 ๐ 0objects have gravity! movement is based on the center of mass, which has to be updated as objects are modified. now it's time for collision detection... ( โ _ โ ) #gamedev
08.04.2025 17:10 โ ๐ 10 ๐ 0 ๐ฌ 0 ๐ 0ah ok, yeah, rand seems like it was made for cryptography and related fields. if you get around to swapping rand out, fastrand is *much* better for games. my understanding is that the bevy_rand crate is partially based on fastrand as well.
08.04.2025 00:35 โ ๐ 0 ๐ 0 ๐ฌ 1 ๐ 0