- User interface
- Player movement
- Basic movement
- Write a proper kinematic character controller from scratch
- Climb slopes
- slide along walls when going into walls instead of zeroeing velocity
- Different maps to play on
- Game modes
- Free for all / Deathmatch
- Wave mode (the game gets more difficult each round, e.g. more enemies are spawned)
- Capture the flag
- Particle effects
- Wall/ground bullet impact
- Blood splatter when hitting enemies
- Enemy AI
- Enemies check if they can see the player and shoot them
- Chasing the player via pathfinding
- Immediately rotate toward the player if enemy was shot
- Going to locations the player made noises
- Multiplayer
- Global Leaderboard
- Lobbies, allow players to create lobbies, change game mode etc
- Level system, weapons for higher levels, need to earn credits to buy new weapons, but can also use weapons of killed higher leveled players
- Weapon animations
- Weapon sway
- Weapon recoil animation (e.g. when shooting kick back)
- Interpolate translation when switching aiming
- Audio Settings menu
- Audio volume
- Music volume
- Graphics settings menu
- Target FPS
- Input settings menu
- Change keybinds of all inputs in the game
- and probably more stuff already implemented and coming soon..
- If you're on linux, install
mold, a linker, for faster iterative compile times
- Ubuntu/Debian:
sudo apt install mold clang - Fedora:
sudo dnf install mold clang - Arch:
sudo pacman -S mold clang
- Bevy itself also needs a couple of dependency. You can find OS-specific installation instructions here
- To run the server:
cargo run -p server <headless|headful>- You can specify either headless or headful. Headless is useful for running where a window cant be created, e.g. servers. Headful will spawn a window, which may be useful to see the map and the spawned players
- You can also emit the argument, and the server will be started in headless mode.
- To run the client:
cargo run -p client
Important
The game assets are not included in this repository. Assets are only provided as part of the compiled game. You can find the compiled game with bundled assets in the latest github action run for your platform. Supported platforms: Linux, macOS (silicon and intel) and Windows
- This project relies heavily on modularization, to be specific, rust modules
- Every module has its own plugin, e.g.
- Everything player related goes into the PlayerPlugin
- Everything related to the user interface goes into the WorldPlugin
- Plugin declarations must always live in the
mod.rsof the given module
- Every module is split up into seperate files, following ECS structure, e.g.
- Components of a module go into
./components.rs - Systems of a module go into
./systems.rs - Messages of a module go into
./messages.rs - and so on
- This makes it very easy to navigate the codebase and scales well
- Components of a module go into
- If a module has sub modules, like for example movement logic of the player, it will be in
movement/mod.rs- Note that a submodule may have its own plugin.
- If the submodule doesnt have lots of logic, all code may be located in its
mod.rsand then be used in the root plugin of given module
- If the submodule doesnt have lots of logic, all code may be located in its
- Note that a submodule may have its own plugin.
- Players are spawned on the server and replicated to all connected clients
- A client can then find its own Player
- Character controller is only running on the client
- Client sends its new position to the server
- The server validates whether this new position was even feasible by a distance check, comparing new position to old position (to be implemented)
- The validated position is stored in
PlayerPositionServer. This component gets replicated to all other clients - All clients can then update the
Transformof that corresponding player- This is done via interpolation so it looks smooth. Without the intermediate component
PlayerPositionServer, we wouldn't be able to add interpolation
- This is done via interpolation so it looks smooth. Without the intermediate component
For shooting:
- Note that the following below is not yet implemented, just client sends message -> raycast on server
- Server saves the position history of a player in a
VecDeque<(u32, Vec3)>- Gets updated each tick and only last ~200ms are saved
- Clients send a ShootRequest to the server, that contains the necessary information together with a
client_tick - Server looks up the position for the given
client_tick - Server spawns temporary colliders to make the raycast
- If hit was sucessful, the
Healthcomponent on the corresponding player is updated
uses:
- bevy for game engine
- avian3d for physics
- skein for bevy <-> blender integration (work with bevy components in blender)
- lightyear for multiplayer