- Every attack is now assembled from traits on its definition instead of per-weapon code: an anchor and path (thrusts, out-and-back, arcs), shared flight physics (gravity, drag, acceleration, homing, and one wall response: end, burst, stick, crawl, bounce, stop, pass, return, latch), and flags like bouncy, drifting, tethered, orbiting, instant and arming. Melee are projectiles too. - Shots have a lifetime and a fade (when damage bottoms out). Range is speed times lifetime. Ricochets and the Vacuum wind lifetime back. - The Vacuum pulls anyone's shots, and its airblast flips them out along the aim, claiming enemies' (fading into your colour). - New trinket: Hourglass, longer projectile lifetime and range. Ropes and chains lengthen with it and the Accelerator. - Fashion: 23 items worn on the head, face or torso, chosen in Profile. - Flamethrower flames hit continuously, the whip coils and sweeps, bouncing shots roll over ramps, and Ricochet relights grenade fuses. - Profile tab, colour tooltips, option hints on every setting, an About tab with credits and links, and the Ithaca font. - Loadouts lock once readied, tomatoes clear with the match, and the round-over pause is 4 seconds. - CC0 license. Tools and CLAUDE.md are no longer tracked, and the web shell moves to web/.
90 lines
4.3 KiB
CMake
90 lines
4.3 KiB
CMake
cmake_minimum_required(VERSION 3.24)
|
|
project(smack_a_brother LANGUAGES C CXX)
|
|
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
# The simulation must run identically on every platform (desktop and web play together), so floating point is kept
|
|
# strict: no fusing multiplies and adds (GCC and arm64 Clang do by default), no fast-math reordering. The maths
|
|
# library's transcendentals are replaced by src/dmath.h.
|
|
if(MSVC)
|
|
add_compile_options(/fp:precise /fp:contract-)
|
|
else()
|
|
add_compile_options(-ffp-contract=off -fno-fast-math)
|
|
endif()
|
|
if(NOT CMAKE_BUILD_TYPE)
|
|
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
|
endif()
|
|
|
|
# SDL: static, with only the video (OpenGL), audio and gamepad pieces the game uses.
|
|
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
|
|
set(SDL_STATIC ON CACHE BOOL "" FORCE)
|
|
set(SDL_OPENGL ON CACHE BOOL "" FORCE)
|
|
set(SDL_JOYSTICK ON CACHE BOOL "" FORCE)
|
|
set(SDL_HIDAPI ON CACHE BOOL "" FORCE)
|
|
set(SDL_VIRTUAL_JOYSTICK ON CACHE BOOL "" FORCE)
|
|
set(SDL_TEST_LIBRARY OFF CACHE BOOL "" FORCE)
|
|
set(SDL_EXAMPLES OFF CACHE BOOL "" FORCE)
|
|
foreach(OPTION RENDER GPU VULKAN CAMERA HAPTIC HIDAPI_LIBUSB POWER SENSOR DIALOG TRAY OPENGLES OFFSCREEN
|
|
DUMMYVIDEO DISKAUDIO DUMMYAUDIO OSS JACK SNDIO KMSDRM IBUS LIBURING)
|
|
set(SDL_${OPTION} OFF CACHE BOOL "" FORCE)
|
|
endforeach()
|
|
add_subdirectory(external/sdl EXCLUDE_FROM_ALL)
|
|
|
|
# simdjson: its single-file build, static, without exceptions.
|
|
add_library(simdjson STATIC external/simdjson/singleheader/simdjson.cpp)
|
|
target_include_directories(simdjson SYSTEM PUBLIC external/simdjson/singleheader)
|
|
target_compile_definitions(simdjson PUBLIC SIMDJSON_EXCEPTIONS=0)
|
|
|
|
include(src/sim.cmake)
|
|
|
|
# Networking: WebRTC data channels between players and a WebSocket to the server. On desktop it's
|
|
# libdatachannel (static, data channels only, no media); in the browser, datachannel-wasm gives the same API over the
|
|
# browser's own WebRTC.
|
|
if(EMSCRIPTEN)
|
|
add_subdirectory(external/datachannel-wasm EXCLUDE_FROM_ALL)
|
|
set(NETWORK_LIBRARY datachannel-wasm)
|
|
else()
|
|
set(NO_MEDIA ON CACHE BOOL "" FORCE)
|
|
set(NO_EXAMPLES ON CACHE BOOL "" FORCE)
|
|
set(NO_TESTS ON CACHE BOOL "" FORCE)
|
|
add_subdirectory(external/libdatachannel EXCLUDE_FROM_ALL)
|
|
set(NETWORK_LIBRARY LibDataChannel::LibDataChannelStatic)
|
|
# The server, which can also be built on its own (see server/CMakeLists.txt).
|
|
add_subdirectory(server)
|
|
endif()
|
|
|
|
file(GLOB SOURCES CONFIGURE_DEPENDS src/*.cpp)
|
|
list(REMOVE_ITEM SOURCES ${SIM_SOURCES})
|
|
add_executable(smack_a_brother ${SOURCES})
|
|
target_include_directories(smack_a_brother SYSTEM PRIVATE external/stb)
|
|
target_link_libraries(smack_a_brother PRIVATE sim SDL3::SDL3-static simdjson ${NETWORK_LIBRARY})
|
|
set_target_properties(smack_a_brother PROPERTIES OUTPUT_NAME smack-a-brother)
|
|
|
|
file(CREATE_LINK ${CMAKE_SOURCE_DIR}/resources ${CMAKE_BINARY_DIR}/resources SYMBOLIC)
|
|
|
|
# Emscripten: RPG_NODE builds a headless copy for node (balance runs and the determinism check), with the resources
|
|
# embedded.
|
|
if(EMSCRIPTEN)
|
|
option(RPG_NODE "Build for node, headless" OFF)
|
|
target_link_options(smack_a_brother PRIVATE -sALLOW_MEMORY_GROWTH=1 -sSTACK_SIZE=1048576)
|
|
if(NOT RPG_NODE)
|
|
# The browser build: WebGL2, the resources preloaded, the prefs folder kept in browser storage, and a page
|
|
# whose canvas fills the window.
|
|
set_target_properties(smack_a_brother PROPERTIES SUFFIX ".html")
|
|
target_link_options(smack_a_brother PRIVATE -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 -lidbfs.js
|
|
"--preload-file=${CMAKE_SOURCE_DIR}/resources/gfx@/resources/gfx"
|
|
"--preload-file=${CMAKE_SOURCE_DIR}/resources/font@/resources/font"
|
|
"--preload-file=${CMAKE_SOURCE_DIR}/resources/sfx@/resources/sfx"
|
|
"--shell-file=${CMAKE_SOURCE_DIR}/web/web_shell.html"
|
|
"--pre-js=${CMAKE_SOURCE_DIR}/web/web_pre.js")
|
|
endif()
|
|
if(RPG_NODE)
|
|
target_link_options(smack_a_brother PRIVATE -sENVIRONMENT=node -sEXIT_RUNTIME=1
|
|
"--pre-js=${CMAKE_SOURCE_DIR}/web/node_pre.js"
|
|
"--embed-file=${CMAKE_SOURCE_DIR}/resources/gfx@/resources/gfx"
|
|
"--embed-file=${CMAKE_SOURCE_DIR}/resources/font@/resources/font")
|
|
endif()
|
|
endif()
|