Game programming in C

Topics related to the API, programming discussions & questions, coding tips, bugs, etc. should go here.
diegzumillo
Posts: 31
Joined: Sat Apr 28, 2018 3:16 am

Game programming in C

Post by diegzumillo »

I'm going through the arctfox's videos, still just getting a feel for the development environment and tools etc. But in the back of my head I'm already trying to figure out how to develop games without object oriented structure. In my limited experience with Pico-8, (LUA script) I usually use tables (structs in c, I think) and functions that mimic some of the functionality of classes. But that feels like swimming against the stream; maybe it works but it's inefficient? I don't know. How do you organize your game in C?

I think a topic to exchange tips on the subject could be useful. I did a forum search before and found a few mentions here and there.
User avatar
Jubatian
Posts: 1561
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Game programming in C

Post by Jubatian »

In plain C you may have no objects, but where you want, you can use object oriented design. Game actors, such as enemies or bullets are often the best represented as objects, you have many of them, needing identical processing. In C, for that, you most often have an array of structures, the structures defining the state of the actor (such as X and Y positions on the map, health and likes), and a set of functions working with it. That's basically a class when done right.

It isn't anything inefficient: in C this is the way to do it, and the result wouldn't be anything less efficient than something produced by a true object oriented language. On the AVR, the only thing to look out for is that function calls have rather high overhead, so small setter and getter functions in very often used code may have noticable overhead (compared to direct access). But design good code first, and only care of optimizing such things where absolutely necessary (due to valid reasons, where you actually discover that it indeed has a performance bottleneck).

So use object-oriented design where it feels natural to do that: there will be a lot of components in any game which would call for this.

Otherwise in general, a normal game loop could possibly look like this:

Code: Select all

    while(1){
        WaitVsync(1); /* Wait for next Vsync (60FPS) */
        Process_Game_Logic(); /* Read inputs, process all game actors */
        Render_Frame(); /* Create next frame */
    }
Depending on the video mode used and its configuration, you might not need to do any render (for example Mode 3 normally can run completely autonomously for a non-scrolling display with sprites), however in more complex games, you will have such tasks, for example scrolling. Some other games might also mix processing game logic and rendering.

What is unique to Uzebox is that normally you do everything within a single frame, so you have no such concerns like frame rate management, or double buffering of screens (like you may have seen when doing SDL stuff for PC). You prepare graphics (or the video mode does it) between frames, and it displays in the next frame.

Hope these are useful for a start!
diegzumillo
Posts: 31
Joined: Sat Apr 28, 2018 3:16 am

Re: Game programming in C

Post by diegzumillo »

I see! that went opposite to what I was doing. I thought "no classes, ok, but I bet I can use functions to do everything and then some" so thanks for the heads up :D And I think a full blown class system, with inheritance and whatnot, only becomes useful when you have a super complex software, which is inherently not the case with uzebox games. All right, then, things make more sense now. Structs, list of objects, looping through them with functions. Sounds good to me.
diegzumillo
Posts: 31
Joined: Sat Apr 28, 2018 3:16 am

Re: Game programming in C

Post by diegzumillo »

I hope it's ok to necro this topic, because I have some more c related questions.

That demo for mode 8 encodes sprite data in an array of char. I assume char is 16 bit, because the code for reading the data uses bit shifting to get 4 different pixels at once. So if char is 16 bit, then we have something like xx xx xx xx, and you do >>2&3 to move the relevant pixel information to the right and mask everything with AND 3. That way we get 4 pixels, each with 4 possible colors in each char.

OK, we can get transparency by simply skipping if it's 0 (or whatever index you define as transparency), but then you only have 3 colors to work with. I'm new to this low level data manipulation so I'm cracking my head trying to find a way to get 4 colors and transparency. And it seems like there is no practical way of doing this because 5 is an odd number of possibilies, so storage waste seems inevitable. But maybe there are clever ways to do that.

The best solution I came up with is each sprite having its own index defined as transparency. That way I can have 4 colors on the screen and 3 colors + transparency on a sprite/object basis. That and just having a second array of some boolean data type but I can't seem to find much about this. It seems there is no booll type in c, or if it does I don't know if it's really one bit.
User avatar
Jubatian
Posts: 1561
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Game programming in C

Post by Jubatian »

diegzumillo wrote: Thu Sep 06, 2018 6:53 pm I hope it's ok to necro this topic, because I have some more c related questions.

That demo for mode 8 encodes sprite data in an array of char. I assume char is 16 bit, because the code for reading the data uses bit shifting to get 4 different pixels at once. So if char is 16 bit, then we have something like xx xx xx xx, and you do >>2&3 to move the relevant pixel information to the right and mask everything with AND 3. That way we get 4 pixels, each with 4 possible colors in each char.
No problem!

That char is 8 bits, Mode 8 is a 2 bits per pixel mode, giving you 4 total colors. One byte is sufficient for 4 pixels! You got it right otherwise, just think it a bit over, 2 bits for one pixel, 2 x 4 = 8 bits for 4 pixels.
diegzumillo wrote: Thu Sep 06, 2018 6:53 pmThe best solution I came up with is each sprite having its own index defined as transparency. That way I can have 4 colors on the screen and 3 colors + transparency on a sprite/object basis. That and just having a second array of some boolean data type but I can't seem to find much about this. It seems there is no booll type in c, or if it does I don't know if it's really one bit.
Those are the two most common solutions, actually. For the second, you can't use booleans (C99 has the _Bool type), as they won't be bits. You have to do the same thing like for pixels: You can encode transparency for 8 pixels in one byte.

If you would like to experiment with something already solving this, you could also check out my experimental Mode 52. You can check out the repo from here: https://github.com/Jubatian/uzebox/tree/mode52 , then to see an example, do a Make here: https://github.com/Jubatian/uzebox/tree ... ples/plane . The mode supports both color index 0 transparency (so you can have 3 colors / sprite) and masked transparency (you can use all 4 colors in a sprite). The Wiki also has an entry for it to start: http://uzebox.org/wiki/Mode_52_Quickstart
diegzumillo
Posts: 31
Joined: Sat Apr 28, 2018 3:16 am

Re: Game programming in C

Post by diegzumillo »

That char is 8 bits
Oh yeah, just a brain fart. I thought 8 and typed 16.
You can encode transparency for 8 pixels in one byte.
Right, that's the same strategy. Clever and no need for bools.

I'm tempted to try other modes and probably will eventually. For now mode 8 is very attractive to me though. I don't need high resolution or lots of colors but I do appreciate more freedom to manipulate the screen. I still don't know how useful this mode actually is yet; that will be more clear when I run some stress tests with lots of pixels and game logic running with it.
diegzumillo
Posts: 31
Joined: Sat Apr 28, 2018 3:16 am

Re: Game programming in C

Post by diegzumillo »

Do we have to load everything at start? It seems like it should be possible to load a set of tiles and sprites for a specific level and then swap for others for the next level.
User avatar
D3thAdd3r
Posts: 3221
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Game programming in C

Post by D3thAdd3r »

Most Uzebox games store graphics and other large resources in flash, statically compiled in, because there is 64K of it versus 4K ram. Then much flash is taken by code of course, and kernel and game variables squeeze the ram, so there is just a fraction of either available. It would be possible to reflash parts of the 64K to swap resources. Some will point to the limited writes before the flash cannot be rewritten again, so it definitely can't be treated just like ram. Personally I am all for the concept, but it is non-trivial I guess since it hasn't been done in a game yet. Needs bootloader support, or theoretical(?) SPM timing hacks. I think Jubatian has laid the ground work to do it in the new bootloader if I remember right.

With SPI ram you can store a lot of resources and easily swap them from the SD card, but the speed is relatively slow. If already using a "slow mode" like mode 8, then maybe the SPI delays are partially nullified in between the shifts and masks. For instance you could do a linear copy of a full Mode 8 screen in about (120/4)*96*18=51,840 cycles. If you need to skip around a lot, then the seek penalties add up quickly.
User avatar
ry755
Posts: 226
Joined: Mon May 22, 2017 6:01 am

Re: Game programming in C

Post by ry755 »

D3thAdd3r wrote: Sun Sep 09, 2018 4:28 am Needs bootloader support, or theoretical(?) SPM timing hacks. I think Jubatian has laid the ground work to do it in the new bootloader if I remember right.
The BootJacker (http://oneweekwonder.blogspot.com/2014/ ... -hack.html) was made to overwrite the bootloader, but with changes it should be possible to make self-modifying code.
diegzumillo
Posts: 31
Joined: Sat Apr 28, 2018 3:16 am

Re: Game programming in C

Post by diegzumillo »

Oh, there's 64k for the program? that's more than I remember! I have to take a look at the wiki again. I guess it's entirely plausible to put every level and every sprite as an 'include' at the top then.
Post Reply