Hacker Newsnew | past | comments | ask | show | jobs | submit | armitage__'s commentslogin

I love custom game engines. Looks fantastic! Will you be sharing the source?


Thanks! For several reasons, most probably and regrettably no, for now at least.

More than happy to talk about any specific part however (e.g. how scenes are handled, the code itself, or how particular features are implemented or optimized).


You talked about using Rust as a better C so I just wanted to ask, do you define any enums with payloads? (also called "sum types" or "tagged unions" in other languages) (edit: also called "algebraic tyeps" and there's an article about it in the front page, though this is a slight misnomer)

Things like

    enum Something {
        One(String),
        Two(i32),
    }
Also, how is your usage of Option? (one such enum)

I think this plus pattern matching is the foundation of Rust's superpowers. It's also very old tech and absolutely not Rust's invention, present in languages like OCaml and SML. Hence the early Rust slogan, "technology from the past, come to save the future from itself"


Actually yes! I use it when passing a texture into a draw function. I have a TexOrColor enum, and when calling the function you either provide an &Image or a &Color. Before that, if I wanted a colored textureless model, I passed a dummy 1x1 texture to sample from.

And of course, Options and pattern matching are easily the best part of the language and very powerful. I am obsessed with things like "let x = if {...}".


Could you talk more about the subset of rust you settled on?

You said you didn't explicitly use simd, but did you do anything to help the optimizer autovectorize like float chunking


It's a very procedural style. I have not used: iterators, lifetimes, Arcs/Boxes/RefCells and whatnot, any kind of generics, data structures other than vecs/arrays, async, and many more. Also avoided functional style, builder patterns...

I only used traits to more easily implement the scenes; a Scene needs to implement a new(), a start() and an update(), so that I can put them in an array and call them like scenes[current_scene_idx].update() from the main loop.

Also, I used some short and simple closures to avoid repeating the same code in many places (like a scope-local write() closure for the menus that wraps drawtext() with some default parameters).

The vast majority of the time is spent in the triangle filling code, where probably some autovectorization is going on when mixing colors. I tried some SIMD there on x86 and didn't see visible improvements.

Apart from obvious and low-hanging fruit (keeping structs simple, keeping the cache happy, don't pass data around needlessly) I didn't do anything interesting. And TBH profiling it shows a lot of cache misses, but I didn't bother further.


Without lifetimes arcs boxes or refcells do you have a lot of clones? Or a lot of unsafe? Or is it mostly single threaded?


It's all single threaded. Just structs being passed around. For example, the mesh drawing call is:

drawmeshindexed(m: &Mesh, mat: &Mat4x4, tex: &Image, uv_off: &TexCoord, li: &LightingInfo, cam: &Camera, buf: &mut Framebuffer)

so there is also no global state/objects. All state is passed down into the functions.

There were some cases that RefCells came in handy (like having an array of references of all models in the scene) and lifetimes were suggested by the compiler at some other similar functions, by I ended up not using that specific code. To be clear, I have nothing against those (on the contrary), it just happened that I didn't need them.

One small exception: I have a Vec of Boxes for the scenes, as SceneCommon is an interface and you can't just have an array of it, obviously.


Thanks! That seems like a nice subset for a lot of use cases. You say it isn't functional, which in rust it is hard to be pure, but if you consider it a spectrum, the style you describe is closer than most game code I've seen.


Right, it's a spectrum, you can't avoid some things (and rightly so).

Another soft rule: no member functions (except for the Scenes); structs are only data, all functions are free functions.

Also no operator overloading, so yes, lots of Vec3::add(&v1, &v2). I was hesitant at first but this makes for more transparent ops (* is dot or cross?) and does not hide the complexity.

The whole thing is around 6-7kloc and I think it would be possible to rewrite in C++ in a day or two.


I don't find the idea of rewriting the subset of a blas library I want to use for each project very fun, but I bet with so few dependencies a stripped binary gets pretty small.


> I have not used: iterators,

Here's a counterpoint: every time you write a for loop in Rust, you are using iterators.


You mean implicitly? I am aware that idiomatic Rust strongly prefers iterators over indices for performance, but in my case, the only place where it really matters is when counting pixels to draw, and there is no kind of collection there, just x,y numbers.


Yep implicitly, for receives an IntoIterator, so it iterates either on an iterator like 0..10 or something that can be converted into an iterator like &myvec

(Note that it was a severe design flaw to make ranges like 0..10 iterators directly rather than just IntoIterator, because this means ranges can't be Copy and as such it's inconvenient to pass them around.. but fortunately they are going to fix that in a new edition)

But actually..

Do you mean you prefer writing for i in 0..myvec.len() and then accessing myvec[i], rather than using for x in &myvec or for x in &mut myvec, and using the x directly? But why?


Interesting, I will look more into this.

To be honest, grepping the source, I found a couple of places with for x in &myvec. Probably tried them while learning the language, they worked and left them there.

But really, I am just more used to the old way. It visually feels more familiar, I have an explicit i to do things, and it's easier to delete/manipulate elements while in the loop and not invalidate anything. It's not that I am against an iterator if it matters and it's better, of course.

In my case, the important loops are like "for i in x0..x1 { draw(i, y); }". Is there a way to turn this into something that, for example, skips the bound checks or optimizes it in any other way?


Where are the Lottie animations coming from? Did you scrape them from other sites? I'm not seeing much info about authors of the animations.


You expect this guy to spend time putting on makeup every time he wants to crank his hog?


It's unlikely that Elon would know how to do that.


The system prompt might just be a textarea in some internal webform.


system prompts are often textfiles, I'm sure he could at least navigate a file directory


Very neat. Would you share some of the prompts you used to generate the pixel art sprite? Super accurate to the photo I provided.


Thanks! Like another user commented below, I think the appeal of the pixel art sprites is that at a lower level of detail it can feel really accurate. 10 different real life red jackets can all end up as the same pixel art representation but each person would recognize it as their jacket! It feels like a form of compression.

On prompting, you can get most of the way there in AI studio on Gemini 2.0 Flash (Image Generation) Experimental by uploading a picture and asking for "a high quality detailed pixel art sprite of this character." Most of the backend annoyance here was iterating to improve prompt adherence (characters not facing the same way, outfits changing between frames, etc).


I am extremely impressed. I literally put my hand fully in front of my face, and it got me spot on. My glasses were partially shown, as was my beard and hair.

That being said, the resolution is such that saying messy hair, full beard, and black glasses, would pretty much get it.


He's probably feeding the webcam pic as img2img no? That'd get you the most details from the original picked up by the AI


I uploaded a photo, though. I didn’t give permission for the camera.

I think it’s simply a matter of it assumed a person, found glasses, and a bit of hair above and below and filled in logically.


Congratulations. Tell us about your "vibe coding" process. What's your programming skill level? What tools did you use to "vibe code"?


It looks to be a free alternative to Forge, and I'm glad to see it.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: