The C++ upgrade of my JavaScript game.
(The video's small size is because GIFs don't have codecs for compression, and GitHub doesn't allow embedding MP4s...)
- OpenGL 3.3 or later
- Earlier versions not supported; 3.3+ is required for instanced rendering of the bullets, allowing far better performance
- Your GPU almost certainly supports this
- Apparently there are some Windows ARM laptops that only support DirectX, so those aren't supported
- 3GHz+ CPU recommended
- Faster CPU -> more bullets on screen
- The game can use more than one core, and the performance increases somewhat, but not a lot
- ~200MB RAM
- No audio requirements, because there's no audio
- OS: Windows x64 or Linux x64
- Mac OS dropped support for OpenGL when they switched to ARM, also I don't have a Mac to test on; if you want to try your luck, look into ANGLE
- ARM should be possible to support but I don't have an ARM device to test on, and RISC-V has extremely few consumer devices
- If using the pre-built Windows binaries, a CPU with SSE4.2 is required (which is satisfied by nearly 100% of CPUs in active use today)
Download here (Windows-only build; Linux has to compile from source, see below)
Clone this repository: git clone https://github.com/khuiqel/tanks-game.git
Visual Studio is the current supported buildsystem for Windows, using the .sln project. The CMakeLists.txt file will work but isn't perfect, so don't use it.
- Note: Compiling profiling builds requires Windows SDK >10.0.19041.0, probably >=10.0.20348.0, due to not having
RelationProcessorDieinLOGICAL_PROCESSOR_RELATIONSHIPfrom<winnt.h>; might be avoidable by dropping to Tracy <0.12 - Build ReleaseDistribution (on the solution, not project)
- Pre-compiled executables are provided if this isn't an option for you
Using CMake & Visual Studio, there's going to be issues but here's what to do:
cmake -S . -B build- If you are interested in testing things out yourself, specify
-DCMAKE_BUILD_TYPE=[Release|Debug], because by default a few things are modified to act like an end-user product (by "a few" I mean just the dev mouse controls are always enabled if you specify the build type)
- If you are interested in testing things out yourself, specify
- Either open the
.slnproject that was just created or runcmake --build build --config [Release|Debug] --target tanks-game- TODO: For some reason, every file gets compiled twice... I don't know why.
- TODO: also needs
res/(andmods/) copied to the build dir - TODO: if you want to disable rpmalloc, comment out the include in
aaa_first.cpp
Using MSYS2, it's a pain but works:
- Prerequisites:
pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain mingw-w64-ucrt-x86_64-glfwand add yourmsys64/ucrt64/binfolder to PATH cmake -S . -B build -G "MinGW Makefiles"cmake --build build -j%NUMBER_OF_PROCESSORS%- TODO: also needs
res/(andmods/) copied to the build dir
Using rpmalloc without <rpnew.h> increases binary size, but a debugger doesn't hit its functions; including <rpnew.h> does hit its functions but segfaults; not sure if it's actually being used...
- Prerequisites: a compiler, Make, CMake, GLFW (optional)
- Ubuntu/Mint:
sudo apt install build-essential cmake libglfw3-dev - Fedora:
sudo dnf install gcc-g++ make cmake glfw-devel - Arch/Manjaro:
sudo pacman -S gcc make cmake glfw - You can compile GLFW from source instead if desired. Disable the
USE_SYSTEM_GLFWoption in CMake and make sure you have the GLFW submodule (git submodule update --initif you didn't recursively download). - If your monitor scaling isn't 100% and you are using Wayland, the game will not fill the whole window until the window is resized, and the dev mouse controls will have an incorrect position. This is a GLFW problem, and fixing it requires using X11 (disable
GLFW_BUILD_WAYLANDin CMake) or using an older version to make X11 the default (git checkout 3.3.10in the submodule).
- Ubuntu/Mint:
cmake -S . -B build(optional and recommended:-DCMAKE_CXX_FLAGS=-march=native -DCMAKE_C_FLAGS=-march=native)- If you are interested in testing things out yourself, specify
-DCMAKE_BUILD_TYPE=[Release|Debug], because by default a few things are modified to act like an end-user product (by "a few" I mean just the dev mouse controls are always enabled if you specify the build type)
- If you are interested in testing things out yourself, specify
cmake --build build -j$(nproc)- TODO: also needs
res/(andmods/) copied to the build dir - Note: On Ubuntu, going fullscreen seems to force the window to the largest monitor, unless "Auto-hide the Dock" is enabled. It appears that Ubuntu forces windows that are too large for the current screen (which means full height is too much due to the dock) to the largest screen.
Performance profiling using Tracy
Requires having the Tracy submodule. Either recursively clone this repository when first downloading, or git submodule update --init if you've already cloned this repository.
Windows: build on ReleaseProfiling
Linux: enable the USE_TRACY option in CMake
Linux + GLFW has a couple problems.
- Fullscreen doesn't work on Wayland, as GLFW cannot set the window position for some reason
- Monitor scaling is always treated as 100%, which results in the game not filling the whole window until a resize, also the dev mouse pos is incorrect
Everyone loves marketing! Enjoy these bullet points and let them compel you to purchase this game for the low price of $0! And it's on sale, or something.
- Unlimited power mixing: grab a powerup, grab another, and keep going, because you can stack as many as you like!
- Non-stop action: Stay on your toes as you dodge hazards to collect a hidden powerup! Respawning is fast and frequent, with many levels to play on.
- Customizability: Several options are available to change! Try setting
ShootingCooldownto 0 and play a few rounds! - Custom levels and powers: Bring out your creativity with custom levels and powers!
- Lots of content: ~22 powers, 12 hazards, ~17 levels, 6 level effects
It's free. Play it if you want, don't if you don't want to.
Making your own levels is now a thing! (Although the levels are very simple, and they take a while to make.) How to do so:
- Navigate to the
modsfolder. - Add a new folder. This will be the name of your mod.
- Add a
levelsfolder to your mod's folder. Your custom levels go here. - Add some text files and make your custom levels!
- Several fields need to be given. I suggest looking at one of the pre-made custom levels and copying it and modifying it.
- Every level needs a
Name(string),Color(3 floats in range [0,1] for RGB),LevelTypes(at least one string; recommended "modname" and "random-modname"), andLevelWeights(1 float for each type; recommended 1.0 is the base weight). - Optionally, levels can contain a
RandomStartPositionCount(int, default = 5, for number of starting positions),RandomStartPositionXValue(float, default = 20, x-distance from edge), andRandomStartPositionYRange(float, default = 256=320-2*32, y-range for starting positions). - Once the assignments have been set,
[LEVEL_START]needs to appear, then you can start adding walls and powers and stuff. - Look at
docs/custom-levels.mdfor more information.
The custom level interpreter is very simple and barebones, so if you want to put something at the center, you have to put the coordinates as 320 160 instead of GAME_WIDTH/2 GAME_HEIGHT/2. Also you can't do any math to your numbers; they need to be the raw numbers (no "sqrt(3)" or "20*8", just "5" or whatever). I know this sucks but adding an expression parser is annoying (although there is a popular library for this task) and adding Lua (or maybe Python?) would've been a much larger hurdle (although this Wikipedia list is much larger than the last time I looked at it so maybe it's easier than I thought?).
Making your own powers is also now a thing! (Although very limited.) How to do so:
- Follow the same steps as making custom levels, but add a
powersfolder in your mod's folder. - Every power needs a
Name(string),Color(3 floats in range [0,1] for RGB),PowerTypes(at least one string; recommended "modname" and "random-modname"), andPowerWeights(1 float for each type; recommended 1.0 is the base weight). - Optionally, powers can contain a
PowerTankDurationMultiplier(float, default = 1.0, for the duration the tank has the power) andPowerAttributes(strings, default = "stack" and "mix", just something to help when randomizing powers) - Once the assignments have been set, do
[TANKPOWER_START]to set up the tank power, then[BULLETPOWER_START]to set up the bullet power. - Check the provided powers for syntax and stuff. They contain basically every operation currently available.
- Look at
docs/custom-powers.mdfor more information.
The custom power interpreter is also very simple and barebones.
Will come soon™.
I didn't find a good way to easily build documentation, so... the documentation is quite lacking. However, there is some. Check the docs folder.
- Visual Studio (2022) - C++ IDE from Microsoft
- Visual Studio Code - Code editor when not on Windows
- GLFW - OpenGL Framework (or Graphics Library Framework); cross-platform way to make windows and get inputs
- Glad2 - OpenGL Loader-Generator; for getting the latest OpenGL commands (where "latest" is >1.1)
- OpenGL Mathematics (GLM) - OpenGL-happy matrix and vector math library
- enkiTS - Thread scheduler for easily managing multithreading
- rpmalloc - Memory allocator, for some extra performance
- stb_image - Image loader for loading the window icon
- Tracy - Performance profiler (note: only used in development, not used in builds meant to be used by users for obvious reasons)
This is my personal project so I won't be taking others' contributions. (Plus I've learned so much and would rather make a sequel at this point.) If you wanna do something with this project, you can fork this repository and do whatever you want.
GNU General Public License v3.0
SPDX-License-Identifier: GPL-3.0-only
- JS Tanks (made by me): tanks.html
- the JS version has significantly less stuff and way worse power mixing, so play this C++ version instead!
- Many people across the Interwebs who made StackOverflow and other forum posts
- Lots of YouTube tutorials, GDC talks, and my CS professors providing assistance
- The vague inspiration I had for this game back when I made it: some top-down Flash tank game. I've tried searching for it multiple times but have never found it, so given my continuously fading memories of that game I played, I'll probably never find out what it actually was. (No, it wasn't Wii Tanks (that's not a Flash game, come on!). I think the game had a more cartoonish than realistic artstyle. I don't remember if there were powerups. My closest guess was some old Atari game remade in Flash, but my searches didn't find anything useful.)
- Super Smash Bros. for being a very fun game
- (Smash Bros the party game, not the competitive fighting game; use items!)
- The Cherno is very helpful for OpenGL
- Factorio's Friday Fun Facts are amazing and got me interested in low-level C++ optimizations
- Nitronic Rush is the other game that made me want to learn C++ in the first place
- Dolphin emulator's Progress Reports for being very in-depth and good reading material
- N++ for just being a good game (also the developers had some good GDC talks and have a useful game development blog)
- Creeper World for also just being a good game
- Outer Wilds for just being a really good game


