• 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

    • The Light of Life? We actually do glow till our Death, study finds by Sayan Sen Image by Rafael Rendon via Pexels A study by researchers at the University of Calgary has found that living organisms produce an extremely faint light known as ultraweak photon emission, and that this glow appears to drop significantly after death. The research was published in the Journal of Physical Chemistry in April 2025 and quickly drew widespread attention, leading to more than 200 news stories about the findings. Ultraweak photon emission (or UPE), sometimes called biophoton emission, refers to tiny amounts of light released by living cells as a result of normal biological activity. A photon is the basic particle of light, and researchers say every living system examined so far, including plants and animals, has been found to emit these photons. The glow is far too faint to be seen by the human eye. “I suppose it has a little to do with people being reminded of auras,” says Dr. Christoph Simon, PhD, one of the authors of the study and a professor in the Department of Physics and Astronomy in the Faculty of Science. “It is a fact that living beings glow. It’s a very weak glow, but it’s there and visible with very sensitive cameras.” According to the study, the light involved is extremely weak, ranging from 10 to 1,000 photons per square centimetre per second across a spectral range of 200 to 1,000 nanometres. For comparison, a nanometre is one-billionth of a metre and is commonly used to measure wavelengths of light. Detecting emissions at such low levels requires highly specialized equipment. To study the phenomenon, researchers used electron-multiplying charge-coupled device (EMCCD) and charge-coupled device (CCD) cameras. These imaging systems are designed to detect extremely small amounts of light, including individual photons, while minimizing background noise. The technology allowed researchers to capture signals that would otherwise be impossible to observe. The team worked with the Human Health Therapeutics Research Centre at the National Research Council of Canada (NRC) in Ottawa to examine photon emissions in mice. Researchers took two-hour exposure images of the animals before and after death and compared the results. “We saw that the level of light that they emit – this biophoton glow – is distinctly different between living and dead animals,” says Dr. Daniel Oblak, PhD, an associate professor in Physics and Astronomy and the corresponding author of the study. The images showed a clear decrease in photon emissions after death across the entire body of each mouse. According to the researchers, this provided direct evidence that living and dead tissue produce different levels of ultraweak photon emission. “It’s a very small amount and it’s, of course, very tricky to detect,” Oblak says. The study grew out of discussions between Simon, whose research interests include quantum biology, and Oblak, whose work focuses on detecting light for quantum communication experiments. Quantum biology is a field that explores whether processes described by quantum physics, which studies matter and energy at very small scales, may also play a role in living systems. “Since I work as a quantum physicist on light detection for quantum communication, I thought that experimentally we have a lot of the tools to be able to detect the light,” Oblak explains. The researchers also investigated UPE in plants and found that the light changed in response to stress. When plants were exposed to higher temperatures or physically injured, their photon emissions increased. Chemical treatments also affected the glow. Among the substances tested, the local anesthetic benzocaine produced the strongest emission response when applied to injured plant tissue. These findings suggest that ultraweak photon emission is closely linked to biochemical and metabolic activity inside living organisms. Metabolism refers to the chemical reactions that allow cells and organisms to stay alive and function. Because these reactions change when an organism experiences stress, injury or disease, researchers believe UPE may provide a way to monitor those changes. The researchers stress that the glow is a physical and biological phenomenon, not a metaphysical one. Oblak says more research is needed to understand exactly how the light is produced and what information it may reveal about the condition of living tissue. “We must understand what that is to figure out what’s happening,” he says. “If we can understand how that relates to certain influences on the body – stress, diseases – then that could be used as a diagnostic tool.” The researchers believe the technique could eventually help scientists study health and disease without invasive procedures. Because UPE can be measured without adding dyes, markers or labels, it may offer a way to monitor whether tissue is healthy, damaged or alive. In plants, it could help researchers better understand how organisms respond to injury, heat and other forms of stress. While the work is still in its early stages, the study demonstrates that ultraweak photon emission imaging can provide a non-invasive and label-free way to observe biological activity. Researchers say the approach could become a useful tool for studying vitality, stress responses and other important processes in both animals and plants. Source: University of Calgary, ACS publication This article was generated with some help from AI and reviewed by an editor. Under Section 107 of the Copyright Act 1976, this material is used for the purpose of news reporting. Fair use is a use permitted by copyright statute that might otherwise be infringing.
    • Damn, I loved this show back in the day.  
    • Rufus 4.15.2393 Beta 2 by Razvan Serea Rufus is a small utility that helps format and create bootable USB flash drives, such as USB keys/pendrives, memory sticks, etc. Despite its small size, Rufus provides everything you need! Oh, and Rufus is fast. For instance it's about twice as fast as UNetbootin, Universal USB Installer or Windows 7 USB download tool, on the creation of a Windows 7 USB installation drive from an ISO (with honorable mention to WiNToBootic for managing to keep up). It is also marginally faster on the creation of Linux bootable USBs from ISOs. A non-exhaustive list of Rufus supported ISOs is available here. It can be especially useful for cases where: you need to create USB installation media from bootable ISOs (Windows, Linux, UEFI, etc.) you need to work on a system that doesn't have an OS installed you need to flash a BIOS or other firmware from DOS you want to run a low-level utility Rufus 4.15.2393 Beta 2 changelog: Add RISC-V 64 support to UEFI:NTFS Improve the guards for using the "silent" option Improve the ability to cancel during write retries Improve progress reporting for compressed image extraction Fix unrestricted XML entity expansion and integer overflow in ezxml parser (courtesy of @esadowski4) [GHSA-55r2-34wg-8mv9] Fix "silent" Windows installation failing at 75% in most cases [#2960] Fix a crash during boot when using UEFI:NTFS on Snapdragon X based ARM64 platforms [#2934] Fix the first WUE option always being checked by default [#2965] Fix an infinite loop when using Windows ISOs that contain multiple WIMs Fix "Enable runtime UEFI media validation" checkbox not always being properly enabled Other WUE improvements/fixes for OneDrive removal and username validation (with thanks to @christian8641) [#2984, #2991] Download: Rufus 4.15 Beta 2 | 1.9 MB (Open Source) Links: Rufus Home Page | Project Page @GitHub | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Tixati 3.43 by Razvan Serea Tixati is a free and easy to use BitTorrent client featuring detailed views of all seed, peer, and file transfer properties. Also included are powerful bandwidth charting and throttling capabilities, and a full DHT implementation. Tixati is one of the most advanced and flexible BitTorrent clients available. And unlike many other clients, Tixati contains NO SPYWARE, NO ADS, and NO GIMMICKS. Tixati portable version is meant to run on a USB flash drive or other portable media. It stores all its configuration files in the same folder as the executable binary files, and all file paths are stored in a format relative to the program executable folder. It is important you do not delete the "tixati_portable_mode.txt" file within the executables folder. This file is what triggers Tixati to run in portable mode. (The executable binaries are actually the same as the standard edition binaries.) When running the portable edition from a USB flash drive, especially one that is formatted in FAT16/FAT32, you may experience some lag when initially loading a new transfer. This is because initializing and allocating large files on flash-based media consumes a greater amount of time and resources compared to a conventional hard-drive. Tixati has the following features: detailed views of all aspects of the swarm, including peers, pieces, files, and trackers support for magnet links, so no need to download .torrent files if a simple magnet-link is available super-efficient peer choking/unchoking algorithms ensure the fastest downloads peer connection encryption for added security full DHT (Distributed Hash Table) implementation for trackerless torrents, including detailed message traffic graphs and customizable event logging advanced bandwidth charting of overall traffic and per-transfer traffic, with separate classification of protocol and file bytes, and with separate classification of outbound traffic for trading and seeding highly flexible bandwidth throttling, including trading/seeding proportion adjustment and adjustable priority for individual transfers and peers bitfield graphs that show the completeness of all downloaded files, what pieces other peers have available, and the health of the overall swarm customizable event logging for each download, and individual event logs for all peers within the swarm expert local file management functions which allow you to move files to a different partition even while downloading is still in progress 100% compatible with the BitTorrent protocol Windows and Linux-GTK native versions available Tixati 3.43 changelog: Several major DHT improvements Added several screening heuristics to filter malicious DHT nodes, prevent Sybil floods Rewrote DHT search algorithms to add support for multi-path lookups Improved DHT logging, more details in several error messages Extended timeout lengths for outgoing queries over I2P Added incoming query / response per second to DHT table status display Updated Regex engine to PCRE2 Faster Search function, scans channel user profiles in much less time Fixed problems with file name parsing and date handling in RSS Faster and more accurate RSS filtering and episode number detection Several optimizations to global text processing functions, such as UTF-8 cleaning, line splitting, and token parsing Complete update of port-mapping UPNP/NAT-PMP engine, added PCP support, mapping over VPN support, and more Several refinements to default gateway detection on Windows / Android, which is used for port-mapping Support for IPv6 interface-scoped addresses, which is sometimes needed for IPv6 gateway detection and port mapping Full support for PCP port remapping, added backup zero-port query in case requested port is rejected New UPNP/NAT-PMP Monitor in Help > Diagnostics New reflected local port/location tracker that analyzes DHT replies to detect true port/location and NAT mapping type New TCP/UDP Ports monitor in Help > Diagnostics, with several statistic and information tabs, and a detailed event log Calculated/reflected local port is now used for port parameter in tracker queries and peer handshake Fixed several problems with Linux Wayland compatibility Completely replaced tray icon functions in Linux, new SNI implementation is now the default with GSI backup Implemented full DBus-Menu server to be used by new SNI tray icon implementation Replaced Linux tray balloon notification DBus client Rewrote auto-shutdown DBus interface for Linux Rewrote sleep inhibit DBus interface for Linux Dropped deprecated Linux dbus-glib dependencies Completely new Windows asynchronous file handling, now using IOCP model with several block-alignment optimizations Better handling of system network resets and interface down/up cycles Added option to fully clear configuration in Settings > Import/Export Remember last option checkboxes when using Import/Export Fixed minor I2P incoming connection routing problems Much faster I2P vanity host name finder Much faster channel user vanity key finder Raised length limit for torrent tracker remote failure messages to 120 from 64 Fixed problems setting download location on a torrent before the meta info is resolved Added location/MOC paths to category pane tooltips Several minor Web Interface fixes Refinements to static and scrolling ellipsizing layout routines Several fixes and improvements to single and multi-line text edit controls Many other minor fixes throughout the user interface A major overhaul of the Android framework has also been done: API target raised to 35, page alignment set to 16K Rewrote all inset processing routines Full rewrite of foreground service, application, and main activity objects New permission request routines Added multi-cast lock request before UPNP/LPDP discovery operations Fixed file permission and locking problems when loading .torrent from web browsers Fixed problems with Z-ordering of modal / non-modal and popup windows Fixed handling of back gesture on newer OS Added status bar icon adjustment based on status bar background color Added option in Settings > UI > Behavior to continue running in tray when task removed from recents App can be closed by swiping away notification Rewrote IME interface, fixed several problems with auto-correct, on-screen keyboard visibility, and cursor positioning Added full support for Android hardware mouse and keyboard function Added full tooltip implementation for Android hovering via mouse or other cursor device Full rewrite of popup menu widgets to better support hardware pointers and keyboard Added mouse cursor updating framework for Android hovering Added Settings > Import/Export to Android builds Added language file support to Android builds Download: Tixati 64-bit | Tixati 32-bit ~20.0 MB (Freeware) Download: Portable Tixati 3.43 | 114.0 MB Download: Tixati 3.43 for Linux | Android View: Tixati Website | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Firefox 152.0.1 by Razvan Serea Firefox is a fast, full-featured Web browser. It offers great security, privacy, and protection against viruses, spyware, malware, and it can also easily block pop-up windows. The key features that have made Firefox so popular are the simple and effective UI, browser speed and strong security capabilities. Firefox has complete features for browsing the Internet. It is very reliable and flexible due to its implemented security features, along with customization options. Firefox includes pop-up blocking, tab-browsing, integrated Google search, simplified privacy controls, a streamlined browser window that shows you more of the page than any other browser and a number of additional features that work with you to help you get the most out of your time online. Firefox key features Enhanced Tracking Protection (ETP) – Blocks trackers, cookies, cryptominers, and fingerprinters by default. Private Browsing Mode – Deletes history, cookies, and temporary files when closed. Lightweight & Fast Performance – Optimized memory usage with efficient page loading. Cross-Platform Sync – Sync bookmarks, passwords, history, and open tabs across devices. Customizable Interface – Toolbars, themes, and extensions can be tailored to user needs. Strong Privacy Controls – Options to manage cookies, permissions, and site data easily. Reader Mode – Strips away clutter for distraction-free reading. Pocket Integration – Save and read articles offline with Pocket built into Firefox. Picture-in-Picture (PiP) – Watch videos in a floating window while multitasking. Extensions & Add-ons – Vast library for productivity, security, and personalization. Built-in PDF Viewer – No need for external software to view PDFs. Firefox Monitor – Alerts users if their email is part of a known data breach. Multi-Account Containers – Isolate browsing sessions (e.g., work, personal, shopping). Performance & Resource Efficiency – Uses fewer system resources than some competitors. Open Source & Community-Driven – Transparent development with global contributions. Firefox 152.0.1 fixes: Fixed frequent crashes affecting users with Intel Raptor Lake processors. (Bug 2039575) Fixed an issue on macOS where choosing a PDF option, such as "Save as PDF", from the system print dialog would send the job to your printer instead of saving a file. (Bug 2047850) Download: Firefox 64-bit | Firefox 32-bit | ARM64 | ~70.0 MB (Freeware) Download: Firefox for MacOS | 146.0 MB View: Firefox Home Page | Release Notes Get alerted to all of our Software updates on Twitter at @NeowinSoftware
  • Recent Achievements

    • One Year In
      hhgygy earned a badge
      One Year In
    • One Month Later
      AMV earned a badge
      One Month Later
    • Week One Done
      AMV earned a badge
      Week One Done
    • Collaborator
      ryansurfer98 went up a rank
      Collaborator
    • One Month Later
      Eurosoft10 earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      514
    2. 2
      +Edouard
      169
    3. 3
      PsYcHoKiLLa
      80
    4. 4
      Steven P.
      73
    5. 5
      Michael Scrip
      72
  • Tell a friend

    Love Neowin? Tell a friend!