25 ms·
Writing a game engine in pure C: The Graphic Initialization
- LinuXY 7y agoFor more inspiration I'd check out the Quake engine source. It's quite the masterpiece. There's also been some modernization over the years by LordHavoc of the DarkPlaces engine https://icculus.org/twilight/darkplaces/ https://icculus.org/twilight/darkplaces/ - I'm constantly impressed how well the HD remaster on DarkPlaces looks on modern 4k hardware.
- bluedino 7y agoThe Wolf3D source is probably an even better start. Much simpler, the bad part is that it's 16-bit Borland C. Andre Lamoth's DOS game programming books are a good read as well, he used 16-bit Microsoft C. Sprinklings of assembler in both.
- jandrese 7y agoSeems like it is going to take a long time to get to a fully functional game if this is the second article and they're only just calling SDL_CreateWindow.
- thrower123 7y agoOne post a week is about as fast as most people can go if they are into nuts-and-bolts technical topics and they are trying to juggle work and life and other demands on their time. That's about the best I could ever manage when I used to be blogging as I learned DirectX. And that was using C#, so you didn't have to boil the ocean and implement all your own fundamental data structures as you go (see the previous post in this series). It's four and a half years into Handmade Hero at this point :-)
- buba 7y agoJust want to explain how things works, i don't know if i'll ever finish this proyect, but if i don't i want the things i did explain crystal clear, i want every concept well presented so every single post in the serie can be a piece by its own and you can learn something. I'm now trying to write two articles a week but it's hard, coding C89 is not fast, there are a lot of cavities and undefined behaivours xD
- buba 7y agoWell, the point is to learn how to build an engine with modern capabilities (those that you are supposed to use with C++ like namespaces, methods, ECS architecture, networking...), SDL is just a tool to not having to write the whole window/input/media/opengl logic from scratch. I could write a SDL tutorial and make a game in 3 hours; it's not as interesting i think, for me the objective is not to write a game but to explain how engines works and desmitify them a little :S But you are right, it'll take a daaamn long time. I've the third and the forth parts almost ready, covering the engine architecture itself, the private scene scope and the image->texture->sprite stuff but i havn't started yet with ECS, fs, configurations, physics, networking... this field is really extense.
- gameswithgo 7y agosuch is life. that is the reality of making games without an engine.
- krapp 7y agoIt's pretty simple to get a working window in SDL, though. That part doesn't need to be complicated.
- bananatron 7y agoAlternative title of this article: "Self mutilation"
- dang 7y agoCould you please not post unsubstantive comments to HN? We're trying for a bit better than internet default here. https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html You might also find these links helpful for getting the spirit of this site: https://news.ycombinator.com/newswelcome.html https://news.ycombinator.com/newswelcome.html https://news.ycombinator.com/hackernews.html https://news.ycombinator.com/hackernews.html http://www.paulgraham.com/trolls.html http://www.paulgraham.com/trolls.html http://www.paulgraham.com/hackernews.html http://www.paulgraham.com/hackernews.html
- mhd 7y agoReading the title my mind immediately went to mov ax, 13h int 10h I'm old.
- raverbashing 7y agoI'm not that old, I would have used a higher level C function to call the bios (And use VESA modes like 640x480x256 - thank Deity for DJGPP)
- mikepurvis 7y agoOh man, the memories. It was such a revelation discovering how much faster it was to POKE pixels directly into memory in QB rather than use the PSET built-in. And then much of that knowledge was directly transferable to Turbo Pascal and later C. it really boggled the mind that it was possible to blt a sprite in rows rather than a pixel at a time, and under the hood, the computer was actually copying 4 bytes per instruction. Anyone else remember implementing the 320 row offset as the sum of two bit shifts? By the early 2000s, I seriously doubt that was any faster, but we all did it anyway for "performance". And don't even get me started on palette hacks— redefining the 256 colors into bars of dark-to-light runs of a single colour, so that you could do smoke or halo effects by just shifting every affected pixel by one or two in either direction. I don't know if he's around these days on HN, but a shout-out to Mark Sibly (Blitz) for bringing a lot of this stuff to the QBasicNews forum back in the day.
- rzzzt 7y agoy << 8 + y << 6 + x (I think the bit shifting and addition trick would still win over an IMUL.) Edit: also, wasn't there a way of (ab-)using LEA to do some of this?
- mikepurvis 7y agoIt seems clang-7 agrees with you— it compiles the multiplication down to shl+add, so the perf is completely identical, see: http://quick-bench.com/CdxqB_qPD3VS5H7igB31FFoqLLo http://quick-bench.com/CdxqB_qPD3VS5H7igB31FFoqLLo
- agentultra 7y agoStarting with state management in the first post is a different approach I wouldn't normally expect. That being said I don't know what it is but I prefer writing games in C. I experiment with higher level languages and use them for rapid prototyping. However, and maybe its simply nostalgia, I always come back to C. And it's not even my favorite language by a long shot. For practically everything else, save for systems programming, I prefer languages like Common Lisp and (more recently) Haskell. Imperative programs are notoriously difficult to comprehend and maintain but there is something about game programming specifically that C leverages which makes it a good fit for game engine development; the mix of pointers and machine-sized types perhaps? I'm not sure. But it works really well.
- buba 7y agoC gives you all control over your machine, there are no obscure libraries, grabage collector or unexpected stuff, if something doesn't work as expected you know you have fcked it up. I'm using C here cause 1st, i like it a lot, and 2nd, i think it's the clearest language out there, you can follow the code execution from start to end and "almost" know what's happening, it doesn't have function overloading, obscure scopes, garbage collectors or automatic weird typing.
- mhh__ 7y agoPerhaps, but C is unsafe both in terms of types and memory (Which has to be considered if choosing C for a project)
- buba 7y agotrue, i'd never do a C89 game from scratch as a profesional project, but this is not a profesional project, it's more like a hobby-academic approach to the lower level of game engine design :D
- Impossible 7y agoHN users tend to parrot the safety line a lot because most people are working on web applications that store somewhat important user data, so gaining access to a remote machine due to a buffer overrun issue is catastrophic, but in games, especially in single player games, safety is less of an issue or even a non-issue. With a multiplayer networked game, cheating, attacks on servers and attacks on other players clients are a concern, but in a game that is entirely or mostly single player the worst outcome of unsafe code is that it crashes to desktop.
- Sir_Cmpwn 7y agoPersonally, I prefer GLFW over SDL: https://www.glfw.org/ https://www.glfw.org/ GLFW just goes from zero to OpenGL context ASAP, plus input events. With SDL I found that their drawing primitives are too limiting for my needs, and if you want to do any custom drawing at all, you need to abandon their drawing primitives entirely and just write GL codel. At that point, GLFW makes more sense. SDL does have a few other nice things like audio support and text rendering, which you'd have to figure out separately with GLFW, but to each their own.
- enriquto 7y agoare there any concrete, tangible advantages of glfw over freeglut? I see the glut api as the paragon of usefulness and simple elegance, and I'm really curious how glfw can be any better than that.
- mrec 7y agoI haven't used glfw, but from the docs it leaves you in control of the main loop, whereas glut takes that over and only offers you callbacks. When I used glut (many many years ago) that was sometimes annoying. glfw doesn't seem to have a function to draw teapots though, which should really rule it out as a serious contender.
- enriquto 7y agolegacy glut does not allow loop control, but freeglut does
- banachtarski 7y agoThere are plenty. Freeglut not being in active development for a while, AFAIK, will not support high-dpi devices (where the window resolution and surface resolution do not match), or newer drivers for different input devices. Freeglut locks you in to OpenGL instead of other rendering APIs. Getting multi-monitor setups up and running is harder. Joystick support is paltry to nonexistent.
- banachtarski 7y ago
- edoo 7y agoThis is an awful SDL engine example. I've made rendering engines before. You should for example have a second windowless openGL context with its own thread so that you can be sending drawing commands at the same time you are updating GPU ram buffers. Generally the main thread is required to be handling input (due to cross platform requirements) and should only be doing that. Everything else including file loading should be running in async threads. It would require you to be a competent programmer though. There are better SDL tutorials from the 90's.
- dang 7y agoThat crosses into personal attack, which we ban people for, and name-calling, which the site guidelines ask you not to do. Would you mind reviewing https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html and taking the spirit of this site more to heart? If you know more than others, the thing to do here is not to put others down, but to offer some of what you know, so we all can learn. Or you can ask about why they did X rather than Y. Perhaps they also know quite a bit, and chose X for an interesting reason.
- edoo 7y agoMaybe you guys can host my 'hello world' article. Blunt criticism rarely damages people. It often drives them to succeed. There are a lot of stories about the best of the best in their fields were shot down at some point in their life. Many assume the criticizers lacked insight, whereas more likely it was the criticism that drove them to their potential. There is little more damaging in today's world than to cheer on someone who is obviously not living up to their potential.
- deleted 7y ago[deleted]
- nocman 7y ago"It would require you to be a competent programmer though." is not blunt criticism. It is simply unkind and unnecessary. You can be blunt without being nasty. While I do sometimes think reactions on HN could use a little "lighten up already", I agree with 'dang' here. You definitely crossed the line in this case.
- obituary_latte 7y agoInterested people may also be interested in Handmade Hero[0]. The game is being developed — from scratch, engine and all — in real-time and streamed by Casey Muratori. It’s cpp technically, but he uses very little and sticks to mostly C if I remember correctly. [0]https://handmadehero.org/ https://handmadehero.org/
- buba 7y agohandmade hero is a piece of art, upvote
- AceJohnny2 7y agoHandmade Hero is an impressive endeavor, but by now it's got over 500 1-2h sessions. That's a lot for anyone to catch up on. Have there been any efforts to write episode summaries/articles on the techniques he demonstrates?
- the_af 7y agoI'm not following Handmade Hero, but out of curiosity: why does it matter how many sessions are there? It's not like watching Game of Thrones where people can spoil it for you. You can follow the tutorial at your own pace :)
- theossuary 7y agoEvery video on his website has pretty great annotations placed on top of them which describes every section of every video, and all the questions at the end of session QA. Go to https://handmadehero.org/watch https://handmadehero.org/watch and scroll down the previous episodes section. Also all the episodes aren't as long as they look, a large chunk of the time is on the QA at the end. That said it is a huge investment at this point, but definitely worth it. Some of his high-level ideas are great, and I've learned a lot.
- mikedelfino 7y agoThere is an excelent episode guide at https://hero.handmade.network/ https://hero.handmade.network/
- deleted 7y ago[deleted]
- yellowarchangel 7y agoThis is moreso "how to start using SDL2". These tutorials exist and are really well thought out here: https://lazyfoo.net/tutorials/SDL/ https://lazyfoo.net/tutorials/SDL/
- buba 7y agothis is not about SDL, it's just an easy way to open a window, import assets, handle events and reproduce sound. Would you like to see a tutorial about how to do that in c89 compatible with windows, mac, Gnu/linux, consoles, etc? it'd take half million lines and 3 years.
- ensiferum 7y agoTheres also wdk which can give you open gl es/desktop context and and this is separate from window creation so you can also create a context for headless rendering. Supports window and linux. https://github.com/ensisoft/wdk/blob/master/sample/triangle.cpp https://github.com/ensisoft/wdk/blob/master/sample/triangle....
- buba 7y agouh, interesting.... C++ tho, but i could port it, i'll give it a glance
- munificent 7y agoAs a tutorial series, I think using plain C is a cool approach and will help illuminate what's going on under the hood and what parts of the engine are really essential. But if you yourself want to write your own game with just you or a small team of like-minded people, I would highly encourage using C++. As long as you don't have too many cooks arguing about which C++ features to throw into the pot, you can pick a subset of C++ that isn't much more complex than C (which is already more complex than most realize) and you'll get a much cleaner, safer language. C++ has saner rules for implicit type conversions, namespaces, overloading, and a cleaner notation for dynamic allocation. Those alone make it a sufficiently "better C" to be worth using in my book. Going farther, even if you don't like "object-oriented programming", I think classes offer modularity and encapsulation features that make them worth using, even if you never once write the keyword "virtual" or use subclassing. (Fun fact: the first version of C++ did not have virtual methods!) I like C and enjoy programming in it, which I've done for over 20 years. I've written a successful open source project in it and am writing a book that uses C as one of the implementation languages. Even so, I generally only use straight C if I'm writing a library that I want C users to be able to consume. Otherwise, I think C++ contains any number of "better C"'s within it, and it's mostly a matter of choosing which better C you want.
- pavlov 7y ago”...it's mostly a matter of choosing which better C you want.” For a beginner that can make things more difficult: in addition to the actual thing you want to learn, you need to first become a capable curator of language features from the past 35 years. JavaScript today has the same problem: you can’t just start writing a web app because two lines into a tutorial you’ll be barraged with “So this is actually an ES2017b.71 feature that we’re enabling using babel-ts-flooginator, therefore you also need TypeScript and that means you need to...” C feels clunky today, but writing more code in exchange for not having to curate the language can be helpful for learning.
- buba 7y agoyep, I choose C89 for this project because there's no Object/Prototype/Class/overloaded bullshit, you get what you wrote and no more, i think it's easier to understand than any other high level language where you have to use obscure things by design. Actually, this tutorial is not just about "building a game engine in C89", it's more about learning the concepts behind game engines, the language and the code is just illustrative examples.
- davidscolgan 7y agoThis is super cool, well done OP! It looks like you've got some pretty in depth and interesting articles around the rest of your site too. Big props to you and everyone else who puts themselves out there and works to create something that helps others.
- nategri 7y agoI finished my first game-ish C/SDL project a few months back, and found it to be a very instructive experience. It compiles to WebAsm so you can fiddle with it here: https://nematode.farm https://nematode.farm
- ursus_bonum 7y agoThis looks like a lot of complexity up front with no foreseeable payoff. Why are we implementing a whole dynamically allocated stack for states before doing anything domain specific? How many states could you possibly be expecting to have in a full game? 3? 12? 100? The examples of states were like the menu, action screen, and pause screen. So it sounds like very few. Drop the realloc'ing and free'ing and just statically allocate N states and be done with it. Save this complexity for something that really needs it. Plus are you going to free the stack any time other than when you quit the app? I doubt it. The OS will free everything for you when you quit so there's no reason to waste time on that either. The code so far looks like mostly a waste of time.
- malkia 7y agoRight now I'm heavy into C++, especially C++17, but mostly due to the current project I'm working on (tools engineer @ gamedev) 20 years ago, my first project was being part of 4 people team porting Metal Gear Solid from PS1 (PSX) to PC. This is when I saw how good written "C" code could be done. Even if it had only japanese comments in the code (understandable). The pure and simple structure, where most of the functions had TCL-like interface: int ACT_Work( int argc, sometype* argv ) { // bit of argc/argv parsing Do_Work() } then above was exposed to a TCL-like scripting language, used for setting up level objects... We are talking about 500-600kb of memory used by the main executable + 300-400kb of 'overlay' memory where "shared, e.g. dll/so-like" code gets replaced depending on what objects needs to be in the game (Mentioned "overlay" as this was very well established practice back in the DOS days). Things really were plain and simple. API-s too. It was so easy to grasp what's going on. Then again, since this was running on what looks like really limited machine, it had to do only such and such. No fancy animation controllers, advanced physics, collision, etc. etc. at some point, especially if it's a content creation tool (think Maya, or any Autodesk product, Houdini, etc.) then you need to be able to handle tons of "nodes", "entities", meta-data, etc. - but when it comes to a game, even nowadays - pre-cooking gets you there, and quick deserializing - either piecewise, or whole sections, and then pointer fixup. Point is, is your game, and engine meant to be content creation tool too?
- malkia 7y agoe.g. "C" is still valid choice, if your data is well organized, known, and no additional heavy modifications are need - e.g. you don't change much - mostly load "pre-cooked " data, play it, keep few (okay dozen, maybe hundreth, even thousand) variables around and that's it. Once you get to the point of needing various tweaks, modifications, changes, more advanced UI, etc. - you may need better suited language, because malloc/free won't cut it for you.
- z3phyr 7y agoIs there a way in modern operating systems to draw pixels directly in software without using any external libraries (Ala SDL or Windows Graphics)? Like just switch mode of a context and draw pixels as you want?