• C Game Engine
    9 replies, posted
Hello I've been writing a game engine in C using SDL 2 and software rasterization techniques. It's pretty simple so far. I have a small pipe that pixels get modified through to allow post processing. Here are the things I've gotten so far: Mouse/Keyboard Input Basic Graphics Lookup tables for sin/cos which use floating values [url]https://puu.sh/uhHwX/e0ac500fe4.png[/url] Vec2/Vec3 structs with a lot of functions to go with. [url]https://puu.sh/uhHsM/708c5359ab.png[/url] 32bit Texture Support & Indexed Texture support [url]https://puu.sh/uhHur/ed75b326cb.png[/url] Here is an example of what I have now: [CODE]Uint32 DefaultPixelFunc(Canvas *canvas, Uint32 src, Uint32 dst) { if ((canvas->flags & FLAG_MODULATION)) { dst = (dst & 0xFF000000) | RGBMul(dst, canvas->modulation); } if ((canvas->flags & FLAG_USE_ALPHA)) { dst = RGBLerp(src, dst, (((dst >> 24) + 1) * canvas->alpha) >> 8); } return dst; }[/CODE] which is assigned to the 'apply' pointer in my Canvas struct [code]typedef struct Canvas { int width; int height; Uint32 *pixels; Uint32 color; Uint32 modulation; Uint32 flags; Uint16 alpha; Rect clip; PixelFunc apply; } Canvas;[/code] Here's an example of one of the functions used to interpolate four channel colors across a triangle [code]inline void SwapPointers(void**a, void**b) { void* c = *b; *b = *a; *a = c; } void DrawRGBScanline(Canvas *canvas, int offset, int x0, int x1, Color* c0, Color* c1) { if (x0 == x1) { return; } if (x0 > x1) { SwapInt(&x0, &x1); SwapPointers(&c0, &c1); } int length = x1 - x0; Color color = *c0; Color colorSlope; ColorSlope(c0, c1, length, &colorSlope); Rect clip = canvas->clip; if (x0 < clip.x0) { real trim = clip.x0 - x0; ColorMulAdd(&color, &colorSlope, trim, &color); x0 = clip.x0; } if (x1 > clip.x1) { x1 = clip.x1; } length = x1 - x0; offset += x0; while (length-- > 0) { SetPixel(canvas, offset, ColorToInt32(&color)); ColorAdd(&color, &colorSlope, &color); offset++; } } inline void SwapColor(Color *a, Color *b) { Color c = *b; *b = *a; *a = c; } void FillRGBTriangle(Canvas *canvas, int x0, int y0, Color c0, int x1, int y1, Color c1, int x2, int y2, Color c2) { if (y2 < y0) { SwapInt(&x0, &x2); SwapInt(&y0, &y2); SwapColor(&c0, &c2); } if (y1 < y0) { SwapInt(&y0, &y1); SwapInt(&x0, &x1); SwapColor(&c0, &c1); } if (y2 < y1) { SwapInt(&y1, &y2); SwapInt(&x1, &x2); SwapColor(&c1, &c2); } if (y0 >= canvas->clip.y1) { return; } int xSlopeAB = 0; Color colorSlopeAB = { 0 }; int xSlopeBC = 0; Color colorSlopeBC = { 0 }; int xSlopeAC = 0; Color colorSlopeAC = { 0 }; if (y0 != y1) { int d = y1 - y0; xSlopeAB = SLOPE16(x0, x1, d); ColorSlope(&c0, &c1, d, &colorSlopeAB); } if (y1 != y2) { int d = y2 - y1; xSlopeBC = SLOPE16(x1, x2, d); ColorSlope(&c1, &c2, d, &colorSlopeBC); } if (y0 != y2) { int d = y2 - y0; xSlopeAC = SLOPE16(x0, x2, d); ColorSlope(&c0, &c2, d, &colorSlopeAC); } x0 <<= 16; x2 = x1 << 16; c2 = c1; x1 = x0; c1 = c0; Rect clip = canvas->clip; if (y0 < clip.y0) { real trim = clip.y0 - y0; x0 += xSlopeAB * trim; x1 += xSlopeAC * trim; ColorMulAdd(&c0, &colorSlopeAB, trim, &c0); ColorMulAdd(&c1, &colorSlopeAC, trim, &c1); y0 = clip.y0; } if (y1 < clip.y0) { real trim = clip.y0 - y1; x2 += xSlopeBC * trim; ColorMulAdd(&c2, &colorSlopeBC, trim, &c2); y1 = clip.y0; } int offset = y0 * canvas->width; for (int i = y1 - y0; i-- > 0;) { if (++y0 > clip.y1) { return; } DrawRGBScanline(canvas, offset, x0 >> 16, x1 >> 16, &c0, &c1); x0 += xSlopeAB; x1 += xSlopeAC; ColorAdd(&c0, &colorSlopeAB, &c0); ColorAdd(&c1, &colorSlopeAC, &c1); offset += canvas->width; } for (int i = y2 - y1; i-- > 0;) { if (++y0 > clip.y1) { return; } DrawRGBScanline(canvas, offset, x2 >> 16, x1 >> 16, &c2, &c1); x2 += xSlopeBC; x1 += xSlopeAC; ColorAdd(&c2, &colorSlopeBC, &c2); ColorAdd(&c1, &colorSlopeAC, &c1); offset += canvas->width; } } [/code] Here is that function in use: [code]void draw(Game *game) { ClearCanvas(game->screen, 0x050505); real x = game->width / 2; real y = game->height / 2; real size = 128; real halfSize = size / 2; FillRGBTriangle(game->screen, x, y - size, RGB(1, 0, 0), x - size, y + halfSize, RGB(0, 1, 0), x + size, y + halfSize, RGB(0, 0, 1) ); }[/code] [img]https://puu.sh/uhHho/88f5754b9b.png[/img]
Scanline drawing? So can you do raster effects?
[QUOTE=RonanZer0;51897225]Scanline drawing? So can you do raster effects?[/QUOTE] Yeah it's scanline drawing. That depends on what you mean by raster effects. Are you talking about post processing? Can you give me an example? edit: I've got a font drawing system going. It supports alpha. I made an extremely simple format that allowed both aliased and antialiased fonts. The only drawback is that they are prerendered, which means scaling is non-existent unless you generate another font of a different size. Here's the LoadFont procedure: [code]Font* LoadFont(const char* filename) { SDL_RWops* ops = SDL_RWFromFile(filename, "r"); if (!ops) { return NULL; } char magic[10]; SDL_RWread(ops, &magic, 7, 1); // ensure we read the right file type if (strcmp(magic, "DFONT1")) { printf("invalid font magic for file: %s\n", filename); return NULL; } // allocate font info Font* font = SDL_malloc(sizeof(Font)); // read one byte into flags SDL_RWread(ops, &font->flags, 1, 1); // read big endian short into height font->height = SDL_ReadBE16(ops); // read 256 ASCII characters for (int i = 0; i < 256; i++) { // short width int width = SDL_ReadBE16(ops); // size of data (each pixel is a byte) int size = sizeof(Uint8)*(font->height * width); // allocate memory for character info Character* c = font->characters[i] = SDL_malloc(sizeof(Character)); // assign values c->width = width; c->data = SDL_malloc(size); // read pixels SDL_RWread(ops, c->data, size, 1); } return font; }[/code] [img]https://puu.sh/usW5H/8c1504b98e.png[/img] I wrote the font generator in Java since Swing makes it super easy to draw fonts. [img]https://puu.sh/usXc2/a9e0d6654e.png[/img]
SNES Mode 7 is a raster effect for example.
[QUOTE=RonanZer0;51909892]SNES Mode 7 is a raster effect for example.[/QUOTE] After looking it up the answer is yes, I can do raster effects.
I doubt you need to add "inline" the compiler know where to use it
man, using SDL has been super frustrating in my experience, cause i always have to go through hella linking errors before i get around to do any actual coding probably a combination of me not really knowing what I'm doing and me not using visual studio
[QUOTE=Octopod;51921882]man, using SDL has been super frustrating in my experience, cause i always have to go through hella linking errors before i get around to do any actual coding probably a combination of me not really knowing what I'm doing and me not using visual studio[/QUOTE] SDL is a good starting point if you have to learn C for some awful reason. It gets you into learning everything with some fun on the side. I started out with SFML though, 10 years ago. It was a much smoother experience IMHO since you also get to learn object orientated programming. It's a whole new topic if you want to actually make video games though. Unless you're doing this for fun or "training your brain" to read complex code then SDL is such a huge waste of time.
[QUOTE=Octopod;51921882]man, using SDL has been super frustrating in my experience, cause i always have to go through hella linking errors before i get around to do any actual coding probably a combination of me not really knowing what I'm doing and me not using visual studio[/QUOTE] I could probably help guide you through linking errors with SDL. I would recommend using an IDE like Visual Studio any way of the week for C/C++, as it definitely helps speed up everything. If you're using GCC then make sure to include the path to the folder containing the SDL2 static .lib files via -L, and then link to SDL2 using -lSDL2main -lSDL2 in your parameters. Add the SDL2 headers to your include path and you should be golden. [QUOTE=AtomiCal;51926990]SDL is a good starting point if you have to learn C for some awful reason. It gets you into learning everything with some fun on the side. I started out with SFML though, 10 years ago. It was a much smoother experience IMHO since you also get to learn object orientated programming. It's a whole new topic if you want to actually make video games though. Unless you're doing this for fun or "training your brain" to read complex code then SDL is such a huge waste of time.[/QUOTE] I want to make video games. My problem is a lack of creativity and artistic ability. I can program my way through a graphical idea but anything beyond that requires more attention to succeed. Maybe I am creative, but with my codes!
[QUOTE=Walrus Viking;51928661] I want to make video games. My problem is a lack of creativity and artistic ability. I can program my way through a graphical idea but anything beyond that requires more attention to succeed. Maybe I am creative, but with my codes![/QUOTE] Apologies for the late reply. It doesn't matter much the approach you take but what matters is staying relevant to what is being used in the industry today. I see literally no company use SDL/SFML today unless they're doing some really low level stuff maybe (I haven't seen that either). Today, Unity and Unreal has taken over as the engines people use for video game development. (Unless you're going into AAA, which is almost impossible to aim for as a beginner) Game Maker has become really good as well. Unity gives you a comfortable starting point as a beginner, has a lot of good tutorials and will give you an entry point into a lot of different fields as well. C# is used in a lot of places. I'm not here to tell you you're wrong, though. Everyone can do whatever they want to do. As long as you're learning programming :) It's just that I did the same exact thing, 10 years ago, when SDL2 was on its way out and SFML was also stuttering to become relevant as game engines were on the rise. It wasn't a waste of time. I did become good at programming. It's just that I wish I had spent my time making games than engines.
Sorry, you need to Log In to post a reply to this thread.