hailthefish

omni-incompetent computer idiot

  • she/her || they/them

cathoderaydude
@cathoderaydude

i used to try to make videogames from time to time and arguably i still do but less frequently. a thing that never stops bothering me - and this is not a Subchost, i just got to thinking about it again cause i saw some posts - is how "it's easy to get started making a game with (tool) and (tool)" is such a common thing to see, and more importantly, seems to work for a lot of people.


cathoderaydude
@cathoderaydude

a comment that has come up several times is, paraphrased:

the reason there's such a big "draw the rest of the owl" gap is because after you get e.g. a basic graphics environment going and like, have a sprite moving around, everything between that and finishing the game is addressing specific micro-issues that are all completely application-dependent and can't be covered in a tutorial format

the thing is, that's exactly the problem. that's what keeps me constantly off-kilter, the feeling of, "wait, oh no, i have to write another little bit of code to handle this specific thing? is that because i didn't write something generally enough?"

if i'm writing a megaman style platformer, and my OC hits the edge of the screen, and I want to flip to a new screen, i... guess I need to write code that moves them from the right edge of the screen to the left? just... manually, i suppose. like a line that literally says "player.x = 0." i guess that's what i have to do. and then i need to add a check to make sure that doesn't drop them in the middle of a solid wall, and if so... uh... do something about it? i guess?

every single step of the way my brain is SCREAMING at me "if you had written an actual simulation you wouldn't be in this situation. that functionality shouldn't need to be hardcoded, it should be a byproduct of movement and environmental code that you never wrote, you just wrote "player.x += player.speed" and now you're digging yourself deeper and deeper into duct-tape spaghetti garbage. it's unsustainable, this will NEVER scale to a finished videogame. it's cute, it feels good to see stuff moving on screen, and you'll make it to a point where you can flip between a few screens, maybe shoot an enemy or something, but as soon as you start trying to build outwards from that and make a finished, serious game like what you see in your minds eye, you'll instantly run into limitations because you just plain didn't do this right, and before long you'll be so buried in tacked-on bandaids that you'll be hardcoding 'make an enemy appear on screen 6' because you didn't generalize enough up front."

and i just never figured out how to get over that, despite the fact that... yeah, from all appearances, that is what you do. you write shit, and if you find out that the engine as you've developed it so far can't account for a situation, you... write a few lines of code that account for that specific situation. and then later maybe you end up in another situation, so you write another few lines of code. and you just keep doing that until you ship. brain will not permit this!


You must log in to comment.

in reply to @cathoderaydude's post:

I flatter myself that I'm quite an accomplished programmer with a number of complex, impressive, successful projects under my belt. And every time I've tried to pick up video game programming for anything more complex than a Twine game my brain runs straight into a brick wall. There's something about the deep simulation-y nature of it that just doesn't work for my thought processes the way programming something to do a task does.

i'm a web app developer and not a game developer, but this is broadly applicable. using a lot of conditional logic ALWAYS feels slimy, even when it's necessary. it feels unsustainable and error prone. additionally i've absolutely had moments where i was relieved to discover that authoritative voices on the frameworks i use were relying on the same shaky-seeming solutions to problems i had come up with. i think this is part of what contributes to the imposter syndrome epidemic in this field.

anyway, relevant xkcd: https://xkcd.com/2030/

Professional gameplay programmer. I LIVE for this kinda stuff, and yeah, it's a very different ballgame than most other programming fields. You basically have to live by a few paradigms.

Programmer time IS iteration time, and iteration time has to be hyper low in video games. The faster you get a working solution, the better.

Gameplay gets nothing for CPU cycles. If I want to hit 60 frames a second, my whole game has to happen in 16ms, and gameplay maybe gets 1 whole ms if I'm lucky some projects. The stupidest most literal operations are usually the cheapest, and the heavy weight math solutions aren't performant enough.

On a related note, stupid code is easier to work with. Video games are pivoting huge swaths of "functionality" in programming terms sometimes daily. If you try and make every piece of the game a clean, usable, correct API, you will never finish a game. If your script just adds 5 to the position of an object every frame, it's stupid easy to change that with almost no technical knock on effects. Again, iteration and performance are everything. Gameplay programming is the bottleneck of most design iteration.

And lastly, the thing that trips up newer gameplay programmers the most, is that you should never solve problems you aren't actually having. You might think "oh if I design in this more general way I might be able to use it for X, Y, and Z in the future" and that gets you killed in gameplay programming. You're doing a ton of work for a hypothetical you don't actually know exists yet, and the majority case is that you discover more with faster iteration that disproves or negates those hypotheticals left and right. The most abstract you get, the more difficult it is to change when your model is proven wrong, changed by designers, changed by technical limitations, etc, etc.

It's great, I love it here, gameplay programmers are a horror to other programming disciplines!

On another note, this original post expresses a lot of the reasons I chose to go to school for Game Programming and Design, because there is that huge gap, and frankly it's hard to get through that gap without either dedicating a lot of independent time to failing at it on your own (which I can't learn that way at all) or getting a half decent sense of direction and scope from a prescribed educational path. It's a unique set of challenges and skills for sure, and a lot of people don't get it. And that's okay. I barely know how to use a database. I can't do graphics programming. UI is my personal hell. But damn do I love wrangling all the physical approximation and non physical actions and player interactions and controls and experiences and camera work and framing and level design and mechanics into a cohesive ball of gameplay. Absolutely live for that chaos.

"Programmer time IS iteration time, and iteration time has to be hyper low in video games. The faster you get a working solution, the better." - preach!!

I think a good example of this mindset is unit-testing. Most programmers are real keen on automated testing - and for good reason! Making sure that your code actually works, and also verifying later that you didn't break it accidentally by adding a new feature - great!

But as someone who came up as a game dev - I struggle with it! Because I'm used working in an environment where it is much more likely that the intended behaviour changes than that the code implementing that behaviour changes. Because even just as a gameplay programmer, often you're making it go, looking at it, then deciding it should actually do a different thing. And if you wrote a unit test first, now you gotta change two things to try out the new version. And ideally you'd be trying out a new version... every few minutes, sometimes? Seconds if it's just tweaking some variables!

(also game logic is usually much less amenable to testing, it only does the thing when it's in the right context with a bunch of other setup, and the output is some graphics and noises that are non-deterministic)

Yeah absolutely never unit test anything :P. Usually the only actually complete description of any given gameplay functionality is the implementation itself. And it's almost never going to even sit unchanged for long enough to worry about it breaking in some subtle way, and when it DOES break in some subtle way, it only really matters if players notice it, and even THAT is so mild a consequence compared to most software fields. It's just a mild inconvenience in someone's entertainment!

This describes my exact frustration with game programming when I'm operating in "technical brain" mode! Which is like, half the time. When I'm operating on that wavelength, I become so fixated on doing things "the right way" that I often don't begin at all, instead falling into the "beginner trap" of endless tutorials and preparing for edge cases that will never happen.

The other half the time, I'm in "art brain" creating elaborate systems and things that I later don't quite understand when it comes time to debug them.

The only trick that has helped me is to not think about it just long enough that I start on something, but not get in too deep that I can still follow what's going on when "technical brain" kicks in. This is a big reason why I gravitate towards WYSIWYG or visual programming driven game engines and construction kits, since it takes care of the systems part so I don't have to worry about doing things "right".

I felt this way when writing the camera routines for ROCKFORCE, an in-progress Doom-engine 2D platformer run-n-gun type.

"ok, the camera always being centered at the player is kinda really jank... great, I'm gonna have to write up a spring tension solver and have the viewport tied to a sproingy tether with a low k-factor... wait.

so like... what if the player character 'pushes' a box surrounding them, that sits on the bottom of the level, and it's tied to the level camera. no, that can't possibly be-"

that's exactly how it works.

hard agree honestly. I think it helps to remember that video game concepts were mostly invented when computers were really slow, and doing anything the "right way" was pretty much impossible. So everything was hacks, just trying to get something working and it turns out that the hacks were general purpose enough that things kept working that way.

honestly yeah, teaching myself how to do any amount of programming has always felt Draw The Rest Of The Owl to me. great way to put it. for me, there's just some fundamental Stuff i'm missing in the whole process. and sometimes a lack of knowing when i'm missing something. and how to find things i don't know i'm missing...

I get this brainworm so bad that I wrote my own game engine just to be more "correct" and "functional" like I am in my other fields of development ... and I still ended up sometimes just having to go "look it collides if it's 5 pixels from center, do not make me do box math" in places. And the underlying graphics code to make that beautiful, elegant, functional-declarative design is a mess, because Canvas is just Like That:tm:.

On the other hand, monkeying about in PICO-8 was kinda liberating, just jabbing stuff in variables and brute force flinging pixels and sprites around ... it's just that kinda dev I never get too far with because the mental model required for all that game state starts to exceed my grasp.

I am an experienced programmer but have always struggled with trying to make games, because my math is quite poor and my spatial reasoning is pretty bad too, and it turns out those help a lot for making games.

Anyway, one thing I found that attempts to address the "draw the rest of the owl" problem is Handmade Hero, where he starts from scratch to make a game. It's like 600+ videos long at this point, but is very incremental, because you see literally all of the code he ever types.

really cool post, thanks for writing this up. i'm sort of on the opposite end of the spectrum -- i love the wild west nature of game programming and all the hacky nonsense feels natural to me, but application programming has always felt overly clinical and claustrophobic to me.

learning game programming also means learning to love hacky ugly solutions that make you go "Seriously? 50 Years Of Progress And This Is Still How We Do It?" and there's not a single game engine in the world that can make that okay

i feel like a lot of disciplines and skills quietly delegate The Rest of the Owl as something to be taught by someone else. which creates a huge gap that is very difficult to cross, unless you know someone who knows the skill, can teach you, and do so in a way that is helpful to you.

(gamedev is specifically egregious because of the aggressive deadlines forcing you to compromise on reasonable solutions)

a huge amount of computing is like this, not just games.

  • how does a kernel decide what pages to put in the page file vs keep in RAM? just drop the least recently used ones.
  • how does raytracing work? just toss a ray at the scene and randomly sample where it bounces. average the results.
    • this techique is actually so robust that "do random bullshit and average the result" is a Named Algorithm (Monte Carlo Simulation).
  • how do we lay out digital logic chips? scatter all the cells on the board and tug them around with virtual springs until they fit, with several layers of correction and postprocessing to slightly make up for the fact that this is stupid.
  • how does an OpenGL driver decide if a buffer should be in vidmem or sysmem? just count how many times it's used from both places, and move it to the most frequent one.
  • it keeps going.

never be afraid of the dumb solution, it's usually fast, and it's easy to debug and make more complex later. doing the complex one first is only good for job security.

one of the more silly ones for chess engines is iterative deeping, which decides "what's the best move" by doing "check all moves to depth 1, then check all moves to depth 2, then check all moves to depth 3, etc" up to some goal depth or until you run out of time. at each step you throw away all the prior work! it seems very silly but 90% of chess engine stuff (that isn't crazy ML stuff) is just "check all the moves"

even the crazy ML stuff is just "check all the moves!" they just prioritize slightly better by doing a shitload of linear algebra!

ML as a whole is deeply stupid too. it's just "what if we multiplied some big matrices together really fast and then kicked the tires on them when it doesn't produce quite the value we wanted." how do you tune it? spend 1 million dollars on computer time to just try a bunch of different attempts at that feedback loop.

don't get me wrong there's definitely some brilliance and deep mathematical and engineering work going on. but there aren't enough hours in the day to have elegant or complex solutions. which is unfortunate because those are usually cool but that's how it goes.

I took ML training at a previous job and it was a massive eye opener. Most ML modeling is so idiotically simplistic that no one believes you when you try to explain how it works. It is literally just the line fit solver on your old graphing calculator, but with 2 dozen axes and grinding out answers by brute force on some GPU farm somewhere.

Oh my god, as someone who knows nothing about programming and has to learn on the spot for shool, sometimes even during exams (they were open book exams, I had access to internet), it feel so accurate. I still know almost nothing about programming, it is a constent struggle, and it seem like other people have it so easy! And that in-between case 1 and case 1 is exactly where I have issues.

Implementing collision systems, platformer mechanics, camera systems, rendering systems, dialog systems, etc. is actually just quite hard, programming-wise.

From the outside they're seen as basic, fundamental parts of games, which makes it seem like they ought to be easy and intuitive to build too, but unfortunately they're just not. You have to develop a lot of knowledge, intuition and experience to make complex games and that takes time and practice. There's no tutorial that can replace that.

One (free) ebook I've found extremely helpful is Game Programming Patterns by Robert Nystrom. It covers the architectural side of game programming, which is rarely touched in tutorials but frequently the hidden wall people run into (it was for me at least).

Yep! It's always a ton of work. Engines help with some things (as long as you don't stray too much from the path they lay out for you), but ultimately you gotta roll up your sleeves and do everything the game is going to include.

I genuinely believe that games are one of the few areas where truly hard programming problems still happen, and yet somehow they're the worst paid while nerds like me can pull 6 figures cranking out HTML.

Don't seem right.

Also gamers should be banned from talking about programming.

Working a normal software job (and making games on the side) has been pretty comfy for me too, ha. From what I've heard and seen I don't envy the working conditions of people in the game industry, nor the customer interactions, that's for sure.

This rings hauntingly with my struggles at video game programming, having failed to make several at this point. I've settled myself with the question of how to make sense of it (though not how to do it) kind of like this:

Games as a concept are fundamentally analog, because the point is to be interacted with by squishy bodies. But they all have rules so that there's a mix of skill and chance to keep things interesting. Some of those rules involve taking turns.

As we know, a digital computer works by dividing everything into numbers, including time. So even in a supposedly real-time analog-like game, every frame (or tick, world update, etc.) is represented by a discrete slice of time where everything happens at once.

In other words, every computer game is turn-based, just usually with most of the decisions being hidden away from the player. And every pixel is a board square. And then you get into the scripted sequences, physics hacks, asset streaming, client-side prediction...

So most of what the computer's being used for is to pretend the rules are different than they are. Hmm.

I've only ever shipped one video game, and I didn't make the movement or combat parts, but one thing that sticks out for me was learning that invincibility frames were invented to keep characters from taking infinity damage when they get hit, and that's basically still how that's done.

"the idea of skipping pixels seemed, and still seems, completely wrong to me. surely that would make the gameplay jittery??"

It does! In fact, in Super Mario World, speedrunners have to evaluate how jittery the screen is to determine whether they're flying at the fastest possible speed, and try to adjust to the optimal speed by tapping right while in flight which cycles the sub-pixels-per-frame at which mario flies, hunting for the fastest option.

Game dev is wild, and game devs are geniuses, and the clever ways things end up finally coming together to form a cohesive system is just staggeringly cool a lot of the time.

explanations of glitches in video games often do a great job of showing what assumptions the game’s systems are making and in what situations those fail. someday i want to make a compilation of such glitch explanations in an educational format.

in this overview of Jellycar’s softbody physics, at 1:38 they explain a primary assumption that the collision detection makes, and then show how it can fail. while technically a “bug”, it’s not something they consider a flaw with the system, because keeping the system acceptably functional, simple, and efficient is a greater priority. there are a ton of other great “wait, that’s it??” realizations throughout this video too.

No kidding - I have a math degree and a lot of experience in programming, and game programming in every game programming framework was hell for me.

I wasn't able to actually start building a video game until I started programming in Rust.

this is one thing I really enjoy about (my beginner attempts at, must underline and bold caveat here!!) reverse-engineering code, the journey from "there's no way it's doing THAT, I must have interpreted this wrong" or "I don't understand this at all so it must be something elegant and complex" to "...no it really is doing THAT."

re: the Rest Of The Owl issue: the missing middle is most likely because everything between beginner and advanced is dealing with specific sub-problems. so say you want to run a webserver. the beginner guide says "here's how to do a basic setup with Python/Django, good luck!" the advanced guide says "here's an innovative and terrifying way to improve the performance of Django," but all the intermediate info is in "why am i getting a type error here?"

most of this info exists but most programmers make the leap from beginner to intermediate via school, and exit school into a world where they have specific error messages they want help with. that's my theory, anyway.

On the subject of "I found exactly two kinds of tutorials..."

One thing I've noticed is that as languages have got 'simpler'/almost usable by normal people. The tutorials have got much worse.

in the ages of C/C++/Java/etc., the most beginner tutorials tended to be "Install IDE ABC_XYZ, then we'll start doing some printing and looping. We'll get to the complex stuff later!"

where Python/Node/etc. tend to be "DO NOT EVEN THINK ABOUT DOING ANY CODING UNTIL YOU'VE SET UP VIRTUAL ENVIRONMENTS, PACKAGE MANAGERS, A VPN TO THE REMOTE SERVER YOU OBVIOUSLY HAVE ACCESS TO, REMOTE GIT REPOSITORY WHICH YOU CLON...."

it's hard to explain why

"install these 15 libraries and docker modules and don't worry about it, don't worry about it, don't ask how any of this works, shh, just open a file and type this line noise and it'll do the thing"

is more mentally abrasive than

_"install this 600 meg blob that has 5000000 OS library files (DO NOT LOOK AT THEM THEY ARE NOT FOR YOU) and then press this magical GUI button and trust me, it's Linking, whatever that is, bam now you have a program"

because by all rights the newer way of doing things is internally simpler, and externally easier, and far more amenable to inspection. yet it somehow just feels far looser and more mysterious and magickal and like you're just supposed to trust this gigantic machine you do not understand

I started learning to code in BASIC on the Commodore 64. The only thing that required was the C64 (or C128) and the manual which explained the keywords and syntax and stuff.

And QBasic in DOS only required the QBasic program, which contained its own extensive documentation.

It took zero effort to set up, and you could literally be drawing things on the screen in QBasic in minutes. Things have definitely gotten worse.

(To be clear, most games in this time were coded in assembly (in the 80s) and C or C++ or possibly pascal (in the 90s). And working with graphics in those in DOS was kind of hell. But given that QBasic came with every copy of DOS 5 and up, it was easier to get into programming and even mess around with doing simple games.)

I'm reading this and thinking back to how all those old computer magazines would just have the example games where you hard code in every aspect of it and I'm genuinely starting to wonder if that's just the entire field. Is it really just hack hardcoded workarounds all the way down?

in reply to @cathoderaydude's post:

This seems to come up in a lot of areas, and it's why I never get much done. In order to make good things, I need to make bad things first (or things that I think are bad, but may turn out to actually be good). It's just a constant niggling in my brain going "do this but good, correct, right". I want to defeat this part of me, more than the part of me that cringes

I don't have this issue in the same way but for sure game dev has no hard lines between "good hacky" and "bad hacky". I feel like the missing piece is to have somebody you trust to ask in those situations where you're stuck, thinking "is this stupid, or is it smart, or is it smartly stupid or stupid in a way that's smart right now".

I have a game dev discord people think is helpful (maybe you're in it? v welcome obvs) and a lot of the time folks come in with one of those "is this as stupid as it seems" questions and the answer tends to come pretty simply and the person can move on, even if the answer was "yes it's bad and you should do it anyway". If your brain can't make that kind of fraught decision, it can help to outsource the decision to another brain so yours can get on with the implementation.

As to whether it's better to write a particular thing in a Cool Very Smart Reusable Way, I think there's a tendency among the people we call "engineers" to take some permanent position one way or the other and as a "technical designer"/game dev generalist person I've run into just as much frustration from both types. Some things can stand to be hastily-erected and ship like that no problem, some things can't, and you can't always know up front. You gotta decide what you're optimising for: your future comfort vs. not getting your brain stuck in the mud right now this second, and pick the road you reckon you're most likely to actually walk down.

i think good game programming is when you can add that other stuff as you need it, and bad game programming is when you need to refactor a bunch of other stuff to do that.

good game programming, you can write the thing to move the player to the other side of the screen, bad game programming you find out that you can't even disable player movement and now the player physics is messing with the screen transition.

what "proper simulation" would create a screen transition like megaman anyways? there's no physics in the screen transition, that's just a seperate thing that happens.

🔘 I'm in this post and I really, really don't like it!

the worst part is it's easier to just bang shit together when you don't know anything so you produce a ton of garbage but like, you produce it, and then you start learning and going "wait, hang on, am i doing this right" and it just spirals into exactly what you said

scream