Build games with SDL, OpenGL and C++ in a Linux environment (ideally WSL) and cross-compile to Windows.
These are all personal preferences, but since I'm not a professional game programmer those are the only constraints I recognize. I do program for a living, but it's all systems programming so I want to maximize how much muscle memory transfers from my day job to my hobby programming. I find Windows a pretty frustrating development environment for C++: Visual Studio has too much UI and not enough personalization, and outside of VS it's pretty rough going (again, all this is subjective). Also since I program all day, I've become highly opinionated about how my work environment should feel to maximize my comfort; Visual Studio 2019 is not easy to customize in the ways I need.
Since I'm a systems programmer, I'm more comfortable expressing and understanding concepts directly in code. Sifting through a general-purpose UI makes me feel a little clumsy and disoriented.
I spend the vast majority of my free computer time in Windows; rebooting to switch between hobby programming and gaming is a no-go. This is also why WSL is my preference.
Go is my favorite language for personal projects, and my first try was to work in Go using SDL bindings. There's a very good sdl2 package that works well, but the instructions for getting it working on windows are a bit intimidating, or at least more than I want to bother maintaining. I did have success skipping the cgo part by loading SDL as a dll, but that was clunky and I never tried to get OpenGL to work.
As described above, I don't consider Visual Studio 2019 to be a viable development environment for personal projects. It's very enterprise-y and covered in useless abstractions (the concepts of "solutions" and "projects" aren't explained anywhere, and they don't seem to add anything that the filesystem doesn't already solve). I find that when I develop in VS2019 I spend as much time wrestling with the editor as I do actually writing code. If I used it professionally things might be different, but I don't so they aren't.
These are both excellent and obvious choices: free, battle-tested in real games, well-documented. I've made several attempts at game programming in Unity and it's great; if I had to use it for my day job I wouldn't mind. The problem is that I feel like I have to shove the editor aside when I want to get at my code, and it's constantly intruding: the Unity UI for running unit tests is terrible; they both (in my opinion) make it hard to organize code effectively.
Unreal is fantastically powerful and since it uses C++ I'm more at home with it, but I've generally struggled to reason about its object model. Also, last I checked its support for procedural mesh generation is still in very early days, and that's the primary tool I use for making games.
This decision is probably where my habits as a systems programmer really show through. Clearly many devs have made excellent creations with both of these, and it's possible
After way more experimentation than I would have liked, I found a setup that works on a WSL Ubuntu distribution.
Install Mingw64 in WSL:
$ sudo apt install mingw-64
Install the SDL mingw dev libraries from http://libsdl.org/download-2.0.php/. I had to edit the Makefile because SDL's Makefile expects mingw to be under /usr/local, but apt put it under /usr. After that edit, just doing $ make cross put everything where it needed to be.
Configure intellisense in vscode: the include paths seem to need /usr/local/SDL2 specifically, since internal SDL headers don't all use the SDL2/ prefix. (Aren't header files fun?)
Each project needs to be able to find SDL2.dll. An easy way to do this is to put the .dll next to the executable, assuming you're always launching the executable from its own directory. A more robust scenario probably involves using an actual installer. Distributing .dll libraries is not something I've ever really looked into.
Alternatively, you can put SDL2.dll somewhere in your %PATH%. For reasons I can't really articulate, I felt this was "messy" but there seems to be plenty of precedent.
I use the following to compile in WSL:
$ i686-w64-mingw32-gcc main.c -o main.exe -lmingw32 -lSDL2main -lSDL2 -mwindows
The order of the -l flags seems to be important. This is sufficient to compile a binary that has no red squiggles and opens an SDL window on Windows. Double-clicking the main.exe from File Explorer launches it just fine.
NEXT STEPS:
Get OpenGL working as well.
Can we cross-compile DirectX like this as well?