• 0

C++/SDL Game Design Guidance


Question

I posted this over on gamedev.net but haven't had any hits yet, hoping some of the bright minds here can give me some guidance.

I have started working on writing a 2D Isometric style game. The idea is to have a persistant world (each tile is unique) and sent from the server where it is then generated (tile object) and then drawn when needed.

The way the game code works right now is that all objects have Draw() and Update() functions that are called every loop by it's parent "Screen" (Static objects, with their own controls/objects/references) Draw() and Update() functions, which in turn are called during the game loop. Basically:

While (!Exited)

ActiveScreen->Update(); -> In turn updating all child objects

ActiveScreen->Draw(); -> In turn drawing all the child objects

While our FPS > Max wait

Inside the Update() functions are things such as positioning, reloading certain objects I free to prevent leaks, checking sdl events (mouse movements, key presses, etc).

Then the Draw() functions determine if that object is visible on the screen, if it is marked visible, if the texture is valid, etc then it runs the SDL Functions to draw it (blit).

The screens Draw() function first clears the screen, runs all the draw functions for the objects that have been programmed then it refreshes the screen so that the changes are visible.

First question, is the above the right concept? I used things I had read/sdl tutorials/way XNA did things to put that bit together. If anyone has a better suggestion I am all ears.

Second question, even though I have the checks to ensure that things show on screen I notice that with a large tile array it slows right down even though it is only displaying a small portion, should I have an array that is filled on the update function that holds all the tile objects instead of looping through all of them at draw time? As each tile is it's own thing and done isometrically I need to redraw each visible tile every time so that they stack properly, so updating only 1 tile at a time isn't doable as it will end up overlapping in the wrong way.

I am sure I will have more questions as I go along. I am pretty experienced with C# and I understand C++ enough to make it work/work right however I am not that well versed in game logic as I do application programming for a living. I want to do this in C++ with SDL instead of using a pre-built solution (XNA,MonoGame,etc) as this will teach me a lot more than using things I am already comfortable with, and a lot of the logic is already handled in.

Link to comment
https://www.neowin.net/forum/topic/1156484-csdl-game-design-guidance/
Share on other sites

8 answers to this question

Recommended Posts

  • 0

I don't have any professional experience with game development, but I have often found it helpful to look at other's source code to see how things are done. I have learned a lot about various programming languages and frameworks that way.

Maybe it would help if you traced through Raven's Jedi Academy source. It is written in C++ and makes use of SDL, just like your game. You might also consider looking at the Ioquake3 source code because it also uses the Quake 3 engine. Effectively, the code is similar because they are both based on the same engine, but ioquake3 has many more features and bug-fixes since Quake 3 has been open-source for much longer.

  • 0

Thanks for those links :)

I am definitely not well versed in game programming, and haven't really had to control things 100%. With .NET 90% of the stuff is already done for me. The one suggestion I have received so far from gamedev was to use space partitioning (treat multiple objects as 1 group and treat them all the same).

This is what I posted in response.

Yea right now I do something like the following for drawing the tiles for example

In gamescreen.cpp's Draw() function

if (ActiveMap != NULL {

ActiveMap->Draw();

}

Active Map's Draw Function()

for (int i = ; i < Tiles.size(); i++) {

if (Tiles[i]->XDrawPos() > -140 && Tiles[i]->XDrawPos() < Client::ActiveWindow->Width &&

Tiles[i]->YDrawPos() > -140 && Tiles[i]->YDrawPos() < Client::ActiveWindow->Height) {

Tiles[i]->Draw();

}

}

Tiles Draw() Is basically just an SDL_Blit of the tile rect on the games sdl_surface at the X/Y Draw position.

I'm not entirely sure on how to grid it, unless I do x > X and x < Z = Group 1 and if pos > X and < Z then draw Group 1. Because I would essentially draw 4 grids each time (as you could be halfway between one and another). Doing this would put 90% of the processing as part of the world loading. However I plan on getting tile info from the server which means I will still need to do processing as I load a tile block.

The drawing of the tiles is where I notice the slow down, if I don't have it drawing tiles/large number of tiles it runs fine. Also, with the other visiblity I just use a boolean inside the object ie)

TextboxLogin->Visible = true/false

And in the draw I just do an

if (Visible) {

Draw it;

}

  • 0

A good way to get more performance is to only draw portions of the screen that have changed. Drawing only visible objects is another.

I currently have properties with X and Y position which is offset by the camera, to which I only draw the objects inside the view port, I also have a Visible boolean which I can specify to draw or not. I was considering redrawing just portions, but the way I have the tiles I have to redraw them all. An option I could do, is separate the tile and edge graphics and only draw the side (edge graphics) on the map edge, then only redraw specific tiles (if a character is overlapping it and moves/other sprite interacts). I could have an isdirty option or something.

  • 0

Unless you're rendering tens of thousands of sprites, if performance is an issue then your drawing code is just plain inefficient. Even crappy integrated graphics can render a lot of sprites without issues if done properly. I'm not familiar with SDL so I don't know how well it performs. Does it use OpenGL acceleration to draw 2d graphics? XNA has a SpriteBatch object that batches draw calls sorted by texture to optimize performance; perhaps there is some similar functionality in SDL - or you'll have to implement it yourself.

Your idea of having every object have a draw and update method is very similar to XNA's basic architecture, however feel free to break from this model as needed. Not every object should be drawable, and not every object should be updated every tick either. I personally tend to have only high-level classes (managers) have an update() method, and sometimes draw if they're responsible for drawing something (like the UI manager or terrain renderer). It's important to maintain a healthy level of separation between gameplay logic and rendering.

  • 0

Unless you're rendering tens of thousands of sprites, if performance is an issue then your drawing code is just plain inefficient. Even crappy integrated graphics can render a lot of sprites without issues if done properly. I'm not familiar with SDL so I don't know how well it performs. Does it use OpenGL acceleration to draw 2d graphics? XNA has a SpriteBatch object that batches draw calls sorted by texture to optimize performance; perhaps there is some similar functionality in SDL - or you'll have to implement it yourself.

Your idea of having every object have a draw and update method is very similar to XNA's basic architecture, however feel free to break from this model as needed. Not every object should be drawable, and not every object should be updated every tick either. I personally tend to have only high-level classes (managers) have an update() method, and sometimes draw if they're responsible for drawing something (like the UI manager or terrain renderer). It's important to maintain a healthy level of separation between gameplay logic and rendering.

I am not rendering that many, at most maybe.. 200 sprites (including the tiles). And the game slows right now. I am not sure how SDL Does it, but as far as I know it does have HWA. I am assuming my drawing code is inefficient but I am not sure how.

I tried to follow how I would do it in XNA (Update/Draw) functions. I will do the following on a draw:

Clear Screen

Draw Nameplates/Portraits

Draw World Tiles

Draw NPCS/Characters top -> bottom (proper layering)

Draw Any Text/Speech

Draw the GUI Controls

I use the update mostly for applying settings/determining if something should be visible or not. Pretty much everything has an update (in the way I am doing it), but the updates are more for applying the font/positioning the font for rendering.

Right now game logic is done primarily through the update procedures and with function calls.

The Rendering/Drawing is more or less the application of the updates. It is essentially a graphical snapshot of what the updates say is happening.

Also, on a side note the memory management is pretty good, using pointers to objects lets me have 3000+ tiles and use pretty much the exact same memory.

  • 0

Which version of SDL are you using? Are you positive you're using hardware acceleration? What resolution are you targeting?

I know from experience using Allegro there's two rendering paths [in Allegro]: software (very slow) and hardware acceleration (very fast). Allegro 4.x used software while Allegro 5.x uses hardware acceleration. I believe the same could be said for SDL, but I'm not experienced with SDL outside of using it just for OpenGL context creation.

  • 0

Which version of SDL are you using? Are you positive you're using hardware acceleration? What resolution are you targeting?

I know from experience using Allegro there's two rendering paths [in Allegro]: software (very slow) and hardware acceleration (very fast). Allegro 4.x used software while Allegro 5.x uses hardware acceleration. I believe the same could be said for SDL, but I'm not experienced with SDL outside of using it just for OpenGL context creation.

SDL 1.2 at first I think I was using SW (SW_SURFACE) read about using HW_SURFACE going to try it and see what it does. But as far as I know it does have HWA (which is the main reason I chose it).

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • That lens of history will burn if you hold it at the right angle... Warn users too late: Shame, Microsoft! That extremely minor update to an obscure Control Panel widget required 2 years of warning. Warn users too early: Shame, Microsoft! We've got better things to do. Pipeline and process be damned, we'll just always be disappointed, eh?
    • Microsoft Paint used to be my favorite Windows app as a kid, and it's still pretty good by Usama Jawad I have been using Windows since the early 2000s, when I was around 10 years old or so. I vaguely remember playing around with Windows 98 and Windows 2000, but that may have been on school PCs which had old operating systems installed. My main OS on the home PC, and the one I recall spending most time with, was Windows XP. At that time, I used the home PC to create Word and PowerPoint documents for school, but a lot of the time, I simply used it to play games. My dad would bring game discs which we would try and install on the PC, sometimes unsuccessfully, and sometimes, we would rely on flash games in the browser, like Bubble Trouble on Miniclip. However, the problem with the latter approach was the internet speed. On a good day, our dial-up internet would offer us speeds of 56 kbps, but on most days, it was closer to 33 kbps. This did not facilitate online gaming as I would often have to wait minutes for a game to load or "draw" on the screen, and trying to download pirated games wasn't simple either. I remember getting tired of waiting for online games to load and just downloading simulator games from the Big Fish Games website instead, only to be disappointed after finding out that I was just being given access to trial versions of the title, and I needed to fork out money to pay for the full version. All of this is to say that it wasn't very easy to find entertainment options on the home PC when I was a kid, due to a number of reasons, mostly outside of my control. This situation pushed me towards a rather unconventional ally: Microsoft Paint. Whenever the internet wasn't working as good as I expected, I would simply spin up Paint and draw complete rubbish on the canvas. Of course, that wasn't always the intention, but it usually happened when I messed up drawing a straight line or something, and then I would give up on that particular piece and simply draw a random collection of objects. Microsoft Paint was extremely accessible and easy to use. Even if you weren't an artist, you could quickly understand the tools at your disposal and how to leverage them on a canvas. The absolute breadth on offer ensured that each painting was truly unique, as you could utilize various combinations of tools like the pencil, paint, spray paint, and more to truly personalize your creation. Since I wasn't particularly good at drawing both on digital screen or a physical screen, I remember that my main style of art would be to insert a bunch of randomly intersecting lines and then fill them with random colors through the paint can. I have trying to replicate that art style in the latest version of Paint below, and as you can see, it's truly Pablo Picasso-esque. The human imagination truly knows no bounds Microsoft Paint kept me occupied for hours and was my best friend when video games on the home PC were inaccessible for one reason or the other. There was no academic or professional reason for which I would need to use Paint, but I still loved using it in my personal time, even if what I created wasn't worth being shown to anyone. It was simply fun. Fast-forward to today, and the situation is mostly the same. Now that I am almost 29 years old, and I still have no reason to use Microsoft Paint in a professional capacity. In fact, I don't even use it in a personal capacity, except to dabble with it from time to time, just to see if core functionalities are still intact. And I'm happy to say that I think Microsoft Paint still offers the same accessibility and inviting experience that it did to me a couple of decades ago, even though its UX has been refreshed and it's been integrated with Copilot features. Interestingly, things could have been a lot different, had Microsoft had its way. Microsoft Paint was marked for deprecation with the Windows 10 Fall Creators Update in 2017, and even began displaying a product retirement alert, urging customers to shift to Paint 3D instead. Fortunately, after consumer backlash, Microsoft reversed course on this decision, and Paint continues to be a native app inside Windows installations that can also be updated quite frequently through the Microsoft Store. Instead, Paint 3D ended up on the chopping block, which is for the better, I think. I have intermittently played around with Microsoft's refreshed Paint experience in the past few years, and I do think it has received worthwhile upgrades. the UI and the UX has been modernized while retaining core functionality, and the app is still fairly easy to use. It doesn't meet any of my use-cases, but I've never really had any use-cases ever, as described previously. Of course, the elephant in the room is the Copilot integration. Personally, I believe that this is one place where Copilot does make sense, environmental concerns aside. I know that a lot of creatives use AI to generate images, and while some may be using professional alternatives, Paint still offers a decent casual experience, with the power of Copilot. Of course, you do need to have a valid Microsoft 365 Copilot license and available credits to use it, but even if you don't, you still get the big Copilot button in the toolbar, unfortunately. All in all, I am glad that Microsoft Paint continues to be a native feature in Windows 11, and a piece of software that has evolved to meet modern needs without cutting off its own roots. It's just an iconic piece of Windows history that was an essential part of my childhood, and while I don't use it anymore, I'm just glad it is still there.
    • 2TB WD_Black SN7100 PCIe Gen4 NVMe SSD drops to its lowest price in over three months by Fiza Ali Amazon is currently offering the 2TB WD_Black SN7100 internal solid-state drive at its lowest price in over three months, so you may want to check it out, if you have been considering a storage upgrade, before the deal dries up (purchase link is toward the end of the article). Featuring a PCIe Gen 4.0 interface and M.2 2280 form factor, the SN7100 promises to deliver sequential read speeds of up to 7,250MB/s and sequential write speeds reaching 6,900MB/s, offering as much as a 35% improvement in performance compared with the previous generation. It also achieves random read speeds of 1,000,000 IOPS and random write speeds of 1,400,000 IOPS. The drive uses Western Digital’s TLC 3D NAND technology for reliable performance and is further supported by a five-year limited warranty. It also offers strong endurance, rated at up to 1,200TBW, making it suitable for demanding workloads such as gaming, content creation, and high-speed recording. Moreover, its DRAM-less architecture claims to improve power efficiency (the SSD relies on system memory for caching via HMB), while the WD_Black Dashboard software enables users to monitor drive health, install firmware updates, and activate Game Mode for potentially better performance. Finally, it operates within an operating temperature range of 0°C to 85°C, and can withstand storage temperatures from -40°C to 85°C. 2TB WD_Black SN7100 PCIe Gen4 NVMe SSD: $242.96 (Amazon US) Check this deal out if you want a 4TB option. Good to know This Amazon deal is U.S. specific, and not available in other regions unless specified. We only use first-party seller links (at the time of article publishing); ensure that you purchase from a first-party seller link only. Check out Today's Deals on Amazon | or our recent tech deals. Become a Prime member (for Students or SNAP) via Neowin Get Prime Access - Prime for half price (for qualifying Medicaid, EBT, SNAP) Subscribe to Prime Video, Audible Plus, Music Unlimited or Kindle Unlimited via Neowin As an Amazon Associate, we earn from qualifying purchases.
    • Hopefully this will fix the issue of no sound I have since last months stupid, and non-removable, Microsoft Corporation AudioProcessingObject Driver Update (1.0.3.56670)
    • It IS confusing! What channel are you in on each device? I'm guessing your 16GB device is on Experimental (formerly known as Dev) and your 128GB is on Beta.
  • Recent Achievements

    • Week One Done
      Supreme Spray LV earned a badge
      Week One Done
    • One Month Later
      Genuinetonerink- Dubai earned a badge
      One Month Later
    • Week One Done
      Genuinetonerink- Dubai earned a badge
      Week One Done
    • One Year In
      hhgygy earned a badge
      One Year In
    • Week One Done
      AMV earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      514
    2. 2
      +Edouard
      163
    3. 3
      PsYcHoKiLLa
      87
    4. 4
      Steven P.
      74
    5. 5
      Michael Scrip
      73
  • Tell a friend

    Love Neowin? Tell a friend!