ann-arcana

Queen of Burgers 🍔

Writer, game designer, engineer, bisexual tranthing, FFXIV addict

OC: Anna Verde - Primal/Excalibur, Empyreum W12 P14

Mare: E6M76HDMVU
. . .



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

another good example of a thing that perennially bugs me: mario jump - we all agree with this; he sure fuckin do my guy. but how?


well it turns out the logic for that is, again, 50 if statements.

on every tick, check if the player is pressing jump. this is a separate line of code; there is no generalizing it, you are not using a switch statement or anything like that because you can combine jumping with many other things. you're going to have a line that says:

if (keys.pressed.contains(keys.jump))

and there is absolutely no getting around that. and it sticks in your craw like a dry pill, the fact you had to do this, that you have a line of hard code that references a specific key, not some kind of Input-Action Conversion Matrix. no. you are asking "is player, mario jump??" in those specific words.

and you can't move it. if you "refactor", you run the risk of breaking mario jump. because somewhere near this is "mario move??" and that massively affects mario jump. so it has to live on Exactly Line 1385, Between Mario Move And Mario Fall.

and then you have to do more ifs. do mario jump? well, do mario stand? do mario collide with something above he? is mario jump already? has it been long enough since mario jump?

and even this is just going way past the sale, because job one is "did the player let go of jump since the last time mario jump?" because you don't want the situation where holding the button causes him to jump again every time he lands.

and that leads to some godforsaken BASTARD line of code like

bool pressedMarioJump;

and it just makes you want to take a shower. it makes sense for this to be a global variable.

it turns out that every single input the player can give is a complex state machine with tons of dependencies that you have to think about and fully internalize, at all times, and every single goddamn line of it is almost literally "a natural-language description of how the game rules work." and it's SO un-computery, it's SO un-programmery, that if the only reason computer ever made any sense to you is because it's logical and procedural, then the enormous stack of utterly arbitrary if statements you have to make, nested 6 deep, will invariably make your skin crawl every time you look at it.

there is no avoiding player.cs


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:

You'd be surprised how many times in the Very Very Expensive and High Profile AAA FPS that I worked on where designers would regularly do a breadth first search of every game object in a scene to find one with a specific name because that's the only way you could reference it in script.

I do like GUI programming and I've come to the realization that as soon as a Person has to touch and interact with controls or the program in general, it turns into this sort of "if X and Y but not Z" type bullshit, because we expect a program to do a lot of stuff and hold a lot of context. The guts of really hard core computing stuff (like compilers or parsers or computational geometry engines or stuff like spice simulators) are just dead-simple math, and they're like, aggressively hard to actually Use. Everyone hates linux because it's all text configurations (and it is). But the amount of effort it'd take to make dialogs or settings pages that are more than "editable tree view of text" is just Intense. The amount of engineering that got the windows control panel to be not immediately aggrivating to use (even if it isn't perfect) is like, months of time, cumulatively. On a big pile of buttons.

And the problem with a video game is that it's minimum 80% user interface. Like, every object in a mario game is analogous to a button of some kind, and mario's the cursor, so the way you expect mario (A Guy, with Guy Properties) to interact with a goomba (mushroom, of a sort) is like soooooo specific. The "draw the rest of the owl" in GUI design is sitting there, thinking like "what if the user closes this window while they have something on the clipboars. What if they go to edit something else. What if they undo something, how much state do we have to keep?" And there's all designs and methods and toolkits to help, but just like every house is wired differently, the way a button or the player character Behaves is just unique, per-program and per-button.

This is speculation and ranting on Your Post, so this bit is absolutely not aimed at you, but like I think why so many UIs are such garbage is because doing this stuff requires empathy that a lot of cheap-fast-quick programming is done by like marketing weirdos or inexperienced programmers who aren't thinking about like. The Emotional and Mental State of the User who is Using our Product. As cliche and weird as that is to say, that's the heart of doing it. Part of the job description is making up a guy and then imagining how they think your program works.

Amazingly none of this is actual programming advice. It's closer to writing advice - write for a specific audience. The actual code and executable, the physical manifestation of the Program, is almost secondary to how it's used. Like you said, the tooling isn't the problem. Rollercoaster Tycoon is famously all assembly, the most spartan possible language, and its UI is pretty nice. It works the way it should, it's relatively intuitive, it's responsive. And I bet it's because Chris Sawyer thought constantly, consistently, and hard about how players were gonna touch the program. There's no hard and fast rules. It's the artistic side of game design and programming.

Honestly, and I literally say this in interviews sometimes even, but I think coming to tech from a humanities background made me a better UI developer specifically for the reason you say: empathy.

So much of my frontend work has been spending sometimes hours fiddling with little bits of CSS or the exact order of state checks in a React component, all because it just ... didn't fucking feel right. It was a pixel off or a frame too slow or the contrast is bad and makes it hard to see and it bugged the shit out of me how did someone leave this here what the fuck i know it's not the ticket but i have to fix this because i'll have to use this later and omfg aaaaagh goddamn you is it a margin or a padding here and ...

And this is web! Web is easier than a lot of those old native GUI frameworks by a country mile. Did you know those crazy motherfuckers had to handwrite resizable elements??? Everyone is making Electron apps because hard as it is to believe, CSS is the sane option.

There are abstractions that have grown up as computers have gotten a little gruntier and we don't all have to be Carmack, classes and stuff to encapsulate state, but that word, state is super key. In terms of the raw amount of state being tracked, simulations (which most games qualify as, but also like the models physicists and weather scientists do) beat out basically every other type of program, except maybe programs that monitor and control an actual physical process. And the state is always changing, always! "You kids and your states, slow down!"

I think there aren't tutorials for those in between topics for the same reason chess mid-games arent theoried out in the way openings and endgames are: by the time you reach that point, any tutorial will only apply to exactly and only the game that it's based on. Those middle ground topics completely depend on all the foundational design decisions that came up before, of which there are enough that a given game quickly becomes 100% unique in it's structure. tell three programmers to make arkanoid from scratch and you'll get three totally different things, none of which are wrong.
I do 100% understand the feeling youre describing though. My college game programming prof told us "the nice thing about programming games is, as long as it looks right to the player, it is right!"
Whether that is liberating or horrifying depends on the individual. I like things to be as abstract, clean and extendable as possible, and that immediately leads to design paralysis when making a game. My only successes have come from setting hard, small and unbreakable scopes for myself, so when that "but what if I want to do... and this and that edge case..." thought appears I can just say NO! that will never matter, because I say so!

Honestly as someone who in a professional context works on backend and occasionally distributed systems that by their nature need to be abstracted and maintainable and reliable and comprehensible, the idea of going back to when I was nine and just writing a bunch of 1:1 descriptions of “if player do thing, then happen” actually sounds soooo appealing, like I’m suddenly dangerously close to getting Far Too Interested in PICO-8 or something

i mean i totally get where you’re coming from with the horror you’re feeling, I see the same thing, that conflict with How Things Should Work, but it wraps around into appeal, like I need to enlarge my programmer brain by reminding myself that It Can Also Work This Way. Probably the same reason that I used to dabble in esoteric languages, which are similarly horrifying from a “computer science with a capital Science” perspective

every time I’ve tried to make a game it’s always felt like “ok this is ugly but this is just a proof of concept, I’ll replace this with Real Code later obviously” and that moment of “haha no i won’t, people just ship games like this” is…a realization

To be honest, while modern game development is still "make sure it's only broken in ways that the player won't notice," looking at stuff like Mario is 100% gonna reveal the jankiest fucking code in the world just due to limitations with memory. Tho, yeah, game code will 100% always be broken compared to normal code. Some stuff just isn't possible to do 60 frames a second, so a lot of SOLID principles tend to just go out the window.

you say this so well. it's something I run into often that feels like an obstacle but I know isn't. anyways the sentence "there is no avoiding player.cs" is now rattling around in my brain forever, giving me a bit of bravery to just make the (big, messy, unwieldy) thing