Sunday, July 14, 2024

Learning SDL Part I

 

While trying to add more feature to the Tanks game, I realized that I need dive deeper into SDL programming. For this reason, I went to https://glusoft.com/sdl2-tutorials/ and downloaded project files. As I didn't have the Visual Studio installed, but only the build tools, so need some tweak to build the examples. The downloaded package comes with solution (.sln) and project (.vcxproj) files. So the project can be built with command like: msbuild 2DLight.sln /p:Configuration=Release /p:Platform="x86"

Also need to update the vcxproj file with v141=>v143, set WindowsTargetPlatformVersion to 10.0.22621.0 which matches my environment, and set AdditionalIncludeDirectories and AdditionalLibraryDirectories to have my SDL2 header file and lib paths, and need to make sure the setting is in 'x64' session if using x64 as platform in above command line. And for the first 2DLight example, would need download https://github.com/trylock/visibility and SDL2_gfx as well. Note SDL_gfx is not from libsdl.org as other SDL lib. And note, there is SDL2_gfx-1.0.4.tar.gz (.zip) and SDL_gfx-2.0.27.tar.gz, though the 2.0.27 is a newer release (Ver 1.0.4 – 11 Feb 2018 vs Ver 2.0.27 – Sun Dec 10 2023), the later is not compatible with SDL2, and though it comes with a SDL2 patch (also needs some tweak such as needs to link with SDL2.lib instead of SDL.lib, rename the project file as SDL2_gfx.vcxproj), the resulted lib may not work with the example code from sdl2-tutorials.

Need to make similar update for SDL2_gfx.vcxproj. And it does not have x86, but Win32, so build command is:
msbuild SDL2_gfx.sln /p:Configuration=Release /p:Platform="Win32"

May see this error: SDL2_gfx-1.0.4\SDL2_gfxPrimitives_font.h(1559,1): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss

Just remove these characters (all are inline comment) should be OK.

For error  SDL2_gfx-1.0.4\SDL2_gfxPrimitives.c(1771,2): error C2169: 'lrint': intrinsic function, cannot be defined, refer to https://www.ferzkopp.net/wordpress/2016/01/02/sdl_gfx-sdl2_gfx. Just comment out the define/implementation as this is already defined as intrinsic function.

There would be a bunch error for building test if those vcxproj files have not been updated, and can be ignored for now. If all test project files got updated, 3 of the 4 tests should work out-of-box, but for TestImageFilter, would not see any thing displayed or printed to terminal. By checking the code, this Image filter test is using 'printf' to log information, and the test has no graphics display. The 'printf' won't spite out anything either, probably due to SDL hijacked the console I/O. The C code also includes 'windows.h' when 'WIN32' is defined. And in fact, w/ or w/o this header file makes no difference. The way to get some print out is replacing 'printf' in the code with 'SDL_Log' call. With SDL_Log, I got 23 of 27 passed OK.

Now, back to the 2DLight example, all build are OK, but will get runtime error as "The application was unable to start correctly. 0xc00007b". Turns out this is due to mixed using x64 build tools to build x86 dll and executable. And the behavior is very weird. So, just avoid doing that.

Now with x86 build environment, build SDL2_gfx as Win32 target, and use other x86 SDL2 lib/dll, also make sure the image/PNG files are copied to the run folder, no more 0xc00007b, however, seeing an assert for vector subscript out of range. Per Copilot:

The vx.reserve(result.size()) call in the code snippet reserves memory for result.size() elements in the vector vx. However, it does not change the size of the vector. The reserve() function is used to allocate memory in advance to prevent frequent reallocations when adding elements to the vector.

To actually change the size of the vector to match the reserved capacity, you can use the resize() function instead of reserve(). The resize() function not only reserves memory but also sets the size of the vector to the specified value.

After I replaced the two reserve() with resize(), the code mostly works as expected, may still see 'Expression: vector subscript out of range' sometimes, likely usually happened when moving the mouse cursor out of the frame, probably due to missing boundary checking. Updated source code was pushed to forked https://github.com/quyq/2DLight-SDL.

If you are using VSCode as editor like me, you may create task.json like this to allow building the project with MSBuild using shortcut 'ctrl+shift+b' (the top half set build env for x86, the bottom half run MSBuild with the solution file):

{
    "version": "2.0.0",
    "windows": {
      "options": {
        "shell": {
          "executable": "cmd.exe",
          "args": [
            "/C",
            // The path of batch file and platform parameter for setting the build env
            "\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/Build/vcvarsall.bat\"",
            "x86",
            "&&"
          ]
        }
      }
    },
    "tasks": [
      {
        "type": "shell",
        "label": "MSBuild.exe build active file",
        "command": "MSBuild.exe",
        "args": [
            "2DLight.sln",
            "-p:Configuration=Release"
        ],
        "problemMatcher": ["$msCompile"],
        "group": {
          "kind": "build",
          "isDefault": true
        }
      }
    ]
}

 If want to use VSCode built-in debugger, may create launch.json as:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "2DLight",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "2DLight.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}/Release",
            "environment": [],
            "console": "externalTerminal"
        }
    ]
}

0 Comments:

Post a Comment