24 Commits

Author SHA1 Message Date
43510ea568 fix main menu on kick
All checks were successful
Linux arm64 / Build (push) Successful in 5m4s
2024-04-12 11:15:08 +02:00
9c6c25b17a add default server config
All checks were successful
Linux arm64 / Build (push) Successful in 5m19s
2024-04-12 11:07:23 +02:00
d8a3cb2785 Piou Piou (#48)
Some checks failed
Linux arm64 / Build (push) Has been cancelled
Fix #8

Reviewed-on: #48
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
2024-04-12 11:06:54 +02:00
27a76519a3 Suppressions d'erreurs Valgrind (#47)
All checks were successful
Linux arm64 / Build (push) Successful in 5m6s
Reviewed-on: #47
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
2024-04-12 10:54:59 +02:00
85585e157f Meilleur panel admin (#45)
All checks were successful
Linux arm64 / Build (push) Successful in 5m6s
Fix #34

Co-authored-by: Morph01 <thibaut6969delastreet@gmail.com>
Reviewed-on: #45
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
2024-04-11 17:29:11 +02:00
c2c6f1f033 C'est important la doc (#43)
All checks were successful
Linux arm64 / Build (push) Successful in 4m59s
C'est très long

Co-authored-by: Morph01 <thibaut6969delastreet@gmail.com>
Reviewed-on: #43
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
2024-04-11 17:17:40 +02:00
07d09332dd Musique de fond (#44)
All checks were successful
Linux arm64 / Build (push) Successful in 5m30s
Fix #7

Reviewed-on: #44
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
2024-04-11 16:59:07 +02:00
747fa13d3a fix action cache (this time it's actually working)
All checks were successful
Linux arm64 / Build (push) Successful in 5m4s
2024-04-11 16:21:49 +02:00
32ca078002 revert non blocking connect
All checks were successful
Linux arm64 / Build (push) Successful in 23m26s
2024-04-11 11:53:30 +02:00
e1efc5065c use leaderboard agin
All checks were successful
Linux arm64 / Build (push) Successful in 23m50s
2024-04-09 20:03:10 +02:00
8795562b42 Fix win (#38)
Some checks failed
Linux arm64 / Build (push) Has been cancelled
Reviewed-on: #38
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
2024-04-09 19:47:46 +02:00
048812090b fix assimp version
All checks were successful
Linux arm64 / Build (push) Successful in 22m33s
2024-04-09 10:08:43 +02:00
ad71bbbdf7 network: add error status
All checks were successful
Linux arm64 / Build (push) Successful in 6m15s
2024-04-06 12:28:45 +02:00
0bb7d28da8 fix join game freeze 2024-04-06 12:24:52 +02:00
8e13bac9d1 fix: build with glew only on CI
All checks were successful
Linux arm64 / Build (push) Successful in 4m55s
2024-04-03 11:09:20 +02:00
76b3057271 fix Android warnings 2024-04-03 10:59:16 +02:00
df4b1641d5 remove unsed assets
All checks were successful
Linux arm64 / Build (push) Successful in 5m42s
2024-04-02 22:46:09 +02:00
7daf2bae0c don't move player when menu is opened
All checks were successful
Linux arm64 / Build (push) Successful in 5m53s
2024-04-02 22:30:58 +02:00
a7b235da38 Possibilité de changer la cadence de tir (#33)
Some checks failed
Linux arm64 / Build (push) Has been cancelled
ajout d'un changement pour la cadence de tir

Co-authored-by: Morph01 <145839520+Morph01@users.noreply.github.com>
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Reviewed-on: #33
Reviewed-by: Simon Pribylski <sim16.prib@gmail.com>
Co-authored-by: Morph01 <thibaut6969delastreet@gmail.com>
Co-committed-by: Morph01 <thibaut6969delastreet@gmail.com>
2024-04-02 22:25:47 +02:00
e27cc29eb0 Réglage de la gravité (#31)
All checks were successful
Linux arm64 / Build (push) Successful in 5m4s
Fix #6

Co-authored-by: Morph01 <145839520+Morph01@users.noreply.github.com>
Reviewed-on: #31
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
2024-03-30 19:38:17 +01:00
d59467dd23 Le laser sort de la main à la première personne (#30)
Some checks are pending
Linux arm64 / Build (push) Waiting to run
Fix #25

Reviewed-on: #30
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
2024-03-30 19:37:40 +01:00
0ed577bbc2 On sait quand on gagne (#29)
Some checks are pending
Linux arm64 / Build (push) Waiting to run
L'écran de fin est mis à jour correctement selon si la victoire nous appartient ou non.
Le cas d'égalité n'est cependant pas traité ! Seulement un joueur peut gagner à l'état actuel

Reviewed-on: #29
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
2024-03-30 19:37:08 +01:00
aa29b9d718 use Vec3 for PlayerController members
All checks were successful
Linux arm64 / Build (push) Successful in 4m39s
2024-03-30 11:53:07 +01:00
1cce7fcd35 remove unused variable
All checks were successful
Linux arm64 / Build (push) Successful in 4m38s
2024-03-30 09:55:07 +01:00
117 changed files with 2957 additions and 561 deletions

View File

@@ -10,7 +10,7 @@ jobs:
- name: Install deps
run : |
apt update
apt install -y libsdl2-dev libassimp-dev libglew-dev
apt install -y libsdl2-dev libassimp-dev libglew-dev
- name: Check out repository code
uses: actions/checkout@v3
@@ -22,11 +22,19 @@ jobs:
actions-cache-folder: '.xmake-cache'
actions-cache-key: 'ubuntu'
- name: Calc deps hash
uses: seepine/hash-files@v1
id: get-hash
with:
patterns: |
**/xmake.lua
**/xmake/*.lua
- name: Packages cache
uses: actions/cache@v4
with:
path: ~/.xmake
key: 'ubuntu-packages'
key: ${{ runner.os }}-${{ steps.get-hash.outputs.hash }}
- name: XMake config
run: xmake f -p linux -y --root
@@ -35,4 +43,4 @@ jobs:
run: xmake --root
- name: Test
run: xmake test --root
run: xmake test --root

BIN
assets/laser.wav Normal file

Binary file not shown.

View File

@@ -1,40 +0,0 @@
# Blender 3.6.4
# www.blender.org
mtllib untitled.mtl
o Cube
v 1.000000 3.829521 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 3.829521 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 3.829521 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 3.829521 1.000000
v -1.000000 -1.000000 1.000000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 0.625000 0.500000
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.125000 0.500000
vt 0.375000 0.500000
vt 0.125000 0.750000
s 0
usemtl Material
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/5/2 3/4/2 7/6/2 8/7/2
f 8/8/3 7/9/3 5/10/3 6/11/3
f 6/12/4 2/13/4 4/5/4 8/14/4
f 2/13/5 1/1/5 3/4/5 4/5/5
f 6/11/6 5/10/6 1/1/6 2/13/6

BIN
assets/sessionD.wav Normal file

Binary file not shown.

View File

@@ -1,37 +0,0 @@
# Blender 3.6.4
# www.blender.org
mtllib void_map.mtl
o Plane
v -30.0 0.000000 30.0
v 30.0 0.000000 30.0
v -30.0 0.000000 -30.0
v 30.0 0.000000 -30.0
v -30.0 0.000000 30.0
v -30.0 0.000000 -30.0
v -30.0 0.000000 30.0
v -30.0 0.000000 -30.0
v -30.0 15.0 30.0
v -30.0 15.0 -30.0
v -30.0 15.0 -30.0
v 30.0 15.0 -30.0
v 30.0 15.0 30.0
v 30.0 15.0 -30.0
v -30.0 15.0 30.0
v 30.0 15.0 30.0
vn -0.0000 1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
s 0
f 1/1/1 2/2/1 4/3/1 3/4/1
f 1/1/1 3/4/1 6/4/1 5/1/1
f 5/1/1 6/4/1 8/4/1 7/1/1
f 7/1/2 8/4/2 10/4/2 9/1/2
f 3/4/3 4/3/3 12/3/3 11/4/3
f 4/3/4 2/2/4 13/2/4 14/3/4
f 2/2/5 1/1/5 15/1/5 16/2/5

View File

@@ -1,38 +0,0 @@
# Blender 3.6.4
# www.blender.org
mtllib void_map2.mtl
o Plane
v -31.562399 0.000000 31.562399
v 31.562399 0.000000 31.562399
v -31.562399 0.000000 -31.562399
v 31.562399 0.000000 -31.562399
v -31.562399 0.000000 31.562399
v -31.562399 0.000000 -31.562399
v -31.562399 0.000000 31.562399
v -31.562399 0.000000 -31.562399
v -31.562399 12.947957 31.562399
v -31.562399 12.947957 -31.562399
v -31.562399 12.885334 -31.562399
v 31.562399 12.885334 -31.562399
v 31.562399 12.806857 31.562399
v 31.562399 12.806857 -31.562399
v -31.562399 12.847334 31.562399
v 31.562399 12.847334 31.562399
vn -0.0000 1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
s 0
usemtl carrelage
f 1/1/1 2/2/1 4/3/1 3/4/1
f 1/1/1 3/4/1 6/4/1 5/1/1
f 5/1/1 6/4/1 8/4/1 7/1/1
f 7/1/2 8/4/2 10/4/2 9/1/2
f 3/4/3 4/3/3 12/3/3 11/4/3
f 4/3/4 2/2/4 13/2/4 14/3/4
f 2/2/5 1/1/5 15/1/5 16/2/5

View File

@@ -7,10 +7,10 @@
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>
#include <cstdint>
namespace blitz {
@@ -40,21 +40,31 @@ class DataBuffer {
DataBuffer& operator=(const DataBuffer& other);
DataBuffer& operator=(DataBuffer&& other);
/**
* \brief Append data to the buffer
*/
template <typename T>
void Append(const T& data) {
std::size_t size = sizeof(data);
std::size_t end_pos = m_Buffer.size();
m_Buffer.resize(m_Buffer.size() + size);
memcpy(&m_Buffer[end_pos], &data, size);
std::memcpy(&m_Buffer[end_pos], &data, size);
}
/**
* \brief Append data to the buffer
*/
template <typename T>
DataBuffer& operator<<(const T& data) {
Append(data);
return *this;
}
// don't use it for binary data !
/**
* \brief Append a string to the buffer
* \warning Don't use it for binary data !
* \param str The string to append
*/
DataBuffer& operator<<(const std::string& str) {
std::size_t strlen = str.length() + 1; // including null character
Resize(GetSize() + strlen);
@@ -62,16 +72,18 @@ class DataBuffer {
return *this;
}
DataBuffer& operator<<(DataBuffer& data) {
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
return *this;
}
/**
* \brief Append data to the buffer from another const buffer
* \param data The buffer to append
*/
DataBuffer& operator<<(const DataBuffer& data) {
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
return *this;
}
/**
* \brief Read some data from the buffer and assign to desired variable
*/
template <typename T>
DataBuffer& operator>>(T& data) {
assert(m_ReadOffset + sizeof(T) <= GetSize());
@@ -80,6 +92,10 @@ class DataBuffer {
return *this;
}
/**
* \brief Read some data from the buffer and assign to the new buffer
* \param data The buffer to assign
*/
DataBuffer& operator>>(DataBuffer& data) {
data.Resize(GetSize() - m_ReadOffset);
std::copy(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), m_Buffer.end(), data.begin());
@@ -87,7 +103,11 @@ class DataBuffer {
return *this;
}
// Don't use it for binary data !
/**
* \brief Read a string from the buffer
* \param str The string to assign in the new buffer
* \warning Don't use it for binary data !
*/
DataBuffer& operator>>(std::string& str) {
std::size_t stringSize =
strlen(reinterpret_cast<const char*>(m_Buffer.data()) + m_ReadOffset) + 1; // including null character
@@ -98,30 +118,55 @@ class DataBuffer {
return *this;
}
/**
* \brief Write some data to the buffer
* \param buffer The buffer to write
* \param amount The amount of data to write
*/
void WriteSome(const char* buffer, std::size_t amount) {
std::size_t end_pos = m_Buffer.size();
m_Buffer.resize(m_Buffer.size() + amount);
memcpy(m_Buffer.data() + end_pos, buffer, amount);
std::memcpy(m_Buffer.data() + end_pos, buffer, amount);
}
/**
* \brief Write some data to the buffer
* \param buffer The buffer to write
* \param amount The amount of data to write
*/
void WriteSome(const std::uint8_t* buffer, std::size_t amount) {
std::size_t end_pos = m_Buffer.size();
m_Buffer.resize(m_Buffer.size() + amount);
memcpy(m_Buffer.data() + end_pos, buffer, amount);
std::memcpy(m_Buffer.data() + end_pos, buffer, amount);
}
/**
* \brief Read some data from the buffer
* \param buffer The buffer to Read
* \param amount The amount of data from the buffer
*/
void ReadSome(char* buffer, std::size_t amount) {
assert(m_ReadOffset + amount <= GetSize());
std::copy_n(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), amount, buffer);
m_ReadOffset += amount;
}
/**
* \brief Read some data from the buffer
* \param buffer The buffer to Read
* \param amount The amount of data from the buffer
*/
void ReadSome(std::uint8_t* buffer, std::size_t amount) {
assert(m_ReadOffset + amount <= GetSize());
std::copy_n(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), amount, buffer);
m_ReadOffset += amount;
}
/**
* \brief Read some data from the buffer
* \param buffer The buffer to Read
* \param amount The amount of data from the buffer
*/
void ReadSome(DataBuffer& buffer, std::size_t amount) {
assert(m_ReadOffset + amount <= GetSize());
buffer.Resize(amount);
@@ -129,64 +174,113 @@ class DataBuffer {
m_ReadOffset += amount;
}
/**
* \brief Resize the buffer
* \param size The new size of the buffer
*/
void Resize(std::size_t size) {
m_Buffer.resize(size);
}
/**
* \brief Reserve some space in the buffer
* \param amount The amount of space to reserve
*/
void Reserve(std::size_t amount) {
m_Buffer.reserve(amount);
}
void erase(iterator it) {
m_Buffer.erase(it);
}
/**
* \brief Clear the buffer
*/
void Clear() {
m_Buffer.clear();
m_ReadOffset = 0;
}
/**
* \brief When the buffer has been read entirely
*/
bool IsFinished() const {
return m_ReadOffset >= m_Buffer.size();
}
/**
* \brief Get the buffer data
*/
std::uint8_t* data() {
return m_Buffer.data();
}
/**
* \brief Get the buffer data
*/
const std::uint8_t* data() const {
return m_Buffer.data();
}
/**
* \brief Get the read offset
*/
std::size_t GetReadOffset() const {
return m_ReadOffset;
}
/**
* \brief Set the read offset
* \param pos The new read offset
*/
void SetReadOffset(std::size_t pos);
/**
* \brief Get the size of the buffer
*/
std::size_t GetSize() const;
/**
* \brief Get the remaining size of the buffer
*/
std::size_t GetRemaining() const;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
/**
* \brief Read a file into the buffer
* \param fileName The name of the file to read
*/
bool ReadFile(const std::string& fileName);
bool WriteFile(const std::string& fileName);
// Don't forget to free the data !
/**
* \brief Write a file into the buffer
* \param fileName The name of the file to write to
*/
bool WriteFile(const std::string& fileName) const;
/**
* \brief Allocate the buffer on the heap
* \warning Don't forget to free the data !
*/
std::uint8_t* HeapAllocatedData() const {
std::uint8_t* newBuffer = new std::uint8_t[GetSize()];
std::memcpy(newBuffer, data(), GetSize());
return newBuffer;
}
bool operator==(const DataBuffer& other) const{
/**
* \brief Operator == to compare two DataBuffer
*/
bool operator==(const DataBuffer& other) const {
return m_Buffer == other.m_Buffer;
}
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
};
/**
* \brief Operator << to write a DataBuffer to an ostream
*/
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer);
} // namespace blitz

View File

@@ -3,7 +3,7 @@
/**
* \file Defines.h
* \brief File containing constants and typedefs
*/
*/
#include <cstdint>
@@ -13,8 +13,20 @@ namespace game {
/**
* \typedef PlayerID
* \brief Represents the identifier of a Player
*/
*/
typedef std::uint8_t PlayerID;
/**
* \enum GameState
* \brief The states of the game
*/
enum GameState : std::uint8_t {
gsNone = 0, /**< Default state */
gsWaiting, /**< Waiting state if the number of players is less than 2 */
gsPreparing, /**< Preparing state until the game start */
gsGame, /**< Game state during the players can shoot and kill ... */
gsEnd, /**< End state of the game : show the winner of the game and the leaderboard*/
};
} // namespace game
} // namespace blitz

View File

@@ -1,7 +1,17 @@
#pragma once
/**
* \file NonCopyable.h
* \brief File containing the blitz::NonCopyable class
*/
namespace blitz {
/**
* \class NonCopyable
* \brief Class used to make a class non copyable
* \note Inherit from this class privately to make a class non copyable
*/
class NonCopyable {
public:
NonCopyable(const NonCopyable&) = delete;

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file VarInt.h
* \brief File containing the blitz::VarInt class
*/
#include <cstddef>
#include <cstdint>
@@ -7,21 +12,46 @@ namespace blitz {
class DataBuffer;
/**
* \class VarInt
* \brief Variable-length format such that smaller numbers use fewer bytes.
*/
class VarInt {
private:
std::uint64_t m_Value;
public:
VarInt() : m_Value(0) {}
/**
* \brief Construct a variable integer from a value
* \param value The value of the variable integer
*/
VarInt(std::uint64_t value) : m_Value(value) {}
/**
* \brief Get the value of the variable integer
*/
std::uint64_t GetValue() const {
return m_Value;
}
/**
* \brief Get the length of the serialized variable integer
*/
std::size_t GetSerializedLength() const;
/**
* \brief Serialize the variable integer
* \param out The buffer to write the serialized variable integer to
* \param var The variable integer to serialize
*/
friend DataBuffer& operator<<(DataBuffer& out, const VarInt& var);
/**
* \brief Deserialize the variable integer
* \param in The buffer to read the serialized variable integer from
* \param var The variable integer to deserialize
*/
friend DataBuffer& operator>>(DataBuffer& in, VarInt& var);
};

View File

@@ -1,51 +1,137 @@
#pragma once
/**
* \file Game.h
* \brief File containing the blitz::game::Game class
*/
#include "Player.h"
#include "blitz/game/Listeners.h"
#include "blitz/misc/ObjectNotifier.h"
#include "blitz/misc/Time.h"
#include <map>
namespace blitz {
namespace game {
/**
* \typedef PlayerMap
* \brief A map of players
*/
typedef std::map<PlayerID, Player> PlayerMap;
enum GameState : std::uint8_t {
gsNone = 0,
gsWaiting,
gsPreparing,
gsGame,
gsEnd,
/**
* \brief The game configuration
* \struct GameConfig
*/
struct GameConfig {
/**
* \brief The gravity applied to players
*/
float Gravity;
/**
* \brief The firing rate of the shoot in RPM (round per minute)
*/
int FiringRate;
};
class Game {
/**
* \class Game
* \brief Class representing a game
*/
class Game : public utils::ObjectNotifier<GameListener> {
protected:
PlayerMap m_Players;
GameState m_GameState;
utils::Timer m_GameTimer;
GameConfig m_Config;
public:
/** \brief Default constructor */
Game() : m_GameState(gsNone) {}
/**
* \brief Update the game with a delta time
* \param delta The time elapsed since the last update in milliseconds
*/
virtual void Tick(std::uint64_t delta) = 0;
/**
* \brief Get a player by its identifier
* \param id The identifier of the player
* \return The player if found, nullptr otherwise
*/
Player* GetPlayerById(PlayerID id);
/**
* \brief Get a player by its identifier (const version)
* \param id The identifier of the player
* \return The player if found, nullptr otherwise
*/
const Player* GetPlayerById(PlayerID id) const;
/**
* \brief Get the players
* \return The map of players
*/
PlayerMap& GetPlayers() {
return m_Players;
}
/**
* \brief Get the players (const version)
* \return The map of players
*/
const PlayerMap& GetPlayers() const {
return m_Players;
}
/**
* \brief Get the game state
* \return The game state
*/
GameState GetGameState() const {
return m_GameState;
}
/**
* \brief Set the game state
* \return The game state
*/
virtual void UpdateGameState(GameState newGameState, std::uint64_t timeRemaining);
/**
* \brief Load the game configuration
* \param config The game configuration to load
*/
void LoadConfig(const GameConfig& config) {
m_Config = config;
}
/**
* \brief Get the game configuration
* \return The game configuration
*/
const game::GameConfig& GetGameConfig() const {
return m_Config;
}
/**
* \brief Add a player to the game
* \param player The identifier of the player
* \param name The name of the player
*/
virtual void AddPlayer(PlayerID player, const std::string& name);
/**
* \brief Remove a player from the game
* \param player The identifier of the player
*/
virtual void RemovePlayer(PlayerID player);
/**
* \brief Get the remaining time of the game
* \return The remaining time of the game in milliseconds
*/
std::uint64_t GetGameStateRemainingTime() const {
return m_GameTimer.GetTimeRemaining();
}

View File

@@ -0,0 +1,49 @@
#pragma once
/**
* \file LeaderBoard.h
* \brief File containing the blitz::game::LeaderBoard class
*/
#include "blitz/game/Player.h"
#include <vector>
namespace blitz {
namespace game {
/**
* \class LeaderBoard
* \brief The leaderboard of the game
*/
class LeaderBoard {
private:
std::vector<Player*> m_Players;
public:
/**
* \brief Add a player to the leaderboard
* \param player The player to add
*/
void AddPlayer(Player* player);
/**
* \brief Remove a player from the leaderboard
* \param player The player to remove
*/
void RemovePlayer(PlayerID player);
/**
* \brief Update the leaderboard
*/
void Update();
/**
* \brief Get the players in the leaderboard ordered by kills
* \return The players
*/
const std::vector<Player*>& GetPlayers() const {
return m_Players;
}
};
} // namespace game
} // namespace blitz

View File

@@ -1,8 +1,18 @@
#pragma once
#include "blitz/common/Defines.h"
#include "blitz/maths/Vector.h"
#include <vector>
namespace blitz {
namespace protocol {
struct ColoredPart;
typedef std::vector<ColoredPart> ColoredText;
} // namespace protocol
namespace game {
class PlayerInputListener {
@@ -11,5 +21,23 @@ class PlayerInputListener {
virtual void OnLocalPlayerShoot(const Vec3f& position, float yaw, float pitch) {}
};
class GameListener {
public:
virtual void OnPlayerJoin(game::PlayerID player) {}
virtual void OnPlayerLeave(game::PlayerID player) {}
virtual void OnGameStateUpdate(game::GameState newState) {}
};
class ClientListener {
public:
virtual void OnTextChatReceived(const protocol::ColoredText& text) {}
virtual void OnSpectatorChange(game::PlayerID player) {}
virtual void OnPlayerShoot(PlayerID player, const Vec3f& position, float yaw, float pitch) {}
virtual void OnClientPlayerJoin() {}
virtual void OnGameConfigUpdate() {}
virtual void OnGameJoin() {}
virtual void OnGameLeave() {}
};
} // namespace game
} // namespace blitz

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file Player.h
* \brief File containing the blitz::game::Player class
*/
#include "blitz/common/Defines.h"
#include "blitz/maths/Vector.h"
#include <cstdint>
@@ -8,13 +13,33 @@
namespace blitz {
namespace game {
/**
* \struct PlayerStats
* \brief The statistics of a player
*/
struct PlayerStats {
/**
* \brief The number of deaths
*/
std::uint16_t m_Deaths;
/**
* \brief The number of kills
*/
std::uint16_t m_Kills;
/**
* \brief The number of shots
*/
std::uint32_t m_ShootCount;
/**
* \brief The number of successful shots
*/
std::uint32_t m_ShootSuccessCount;
};
/**
* \class Player
* \brief The player of the game
*/
class Player {
private:
PlayerID m_ID;
@@ -25,89 +50,172 @@ class Player {
float m_Pitch;
float m_HP;
bool m_IsBot;
public:
Player(PlayerID id) : m_ID(id), m_Yaw(0), m_Pitch(0), m_HP(100), m_IsBot(false) {}
PlayerStats m_Stats{};
public:
/**
* \brief Default constructor
* \param id The ID of the player
*/
Player(PlayerID id) : m_ID(id), m_Yaw(0), m_Pitch(0), m_HP(100), m_IsBot(false) {}
/**
* \brief Get the ID of the player
* \return The ID of the player
*/
PlayerID GetID() const {
return m_ID;
}
/**
* \brief Get the name of the player
* \return The name of the player
*/
const std::string& GetName() const {
return m_Name;
}
/**
* \brief Set the name of the player
* \param name The name of the player
*/
void SetName(const std::string& name) {
m_Name = name;
}
/**
* \brief Get the position of the player
* \return The position of the player
*/
const Vec3f& GetPosition() const {
return m_Position;
}
/**
* \brief Set the position of the player
* \param newPos The new position of the player
*/
void SetPosition(const Vec3f& newPos) {
m_Position = newPos;
}
/**
* \brief Add a position to the player
* \param dPos The position to add
*/
void AddPosition(const Vec3f& dPos) {
m_Position += dPos;
}
/**
* \brief Get the velocity of the player
* \return The velocity of the player
*/
const Vec3f& GetVelocity() const {
return m_Velocity;
}
/**
* \brief Set the velocity of the player
* \param newVelocity The new velocity of the player
*/
void SetVelocity(const Vec3f& newVelocity) {
m_Velocity = newVelocity;
}
/**
* \brief Get the yaw of the player
* \return The yaw of the player in radians
*/
float GetYaw() const {
return m_Yaw;
}
/**
* \brief Set the yaw of the player
* \param yaw The yaw of the player in radians
*/
void SetYaw(float yaw) {
m_Yaw = yaw;
}
/**
* \brief Add a yaw to the player
* \param dYaw The yaw to add in radians
*/
void AddYaw(float dYaw) {
m_Yaw += dYaw;
}
/**
* \brief Get the pitch of the player
* \return The pitch of the player in radians
*/
float GetPitch() const {
return m_Pitch;
}
/**
* \brief Set the pitch of the player
* \param pitch The pitch of the player in radians
*/
void SetPitch(float pitch) {
m_Pitch = pitch;
}
/**
* \brief Add a pitch to the player
* \param dPitch The pitch to add in radians
*/
void AddPitch(float dPitch) {
m_Pitch += dPitch;
}
/**
* \brief Get the HP of the player
* \return The HP of the player
*/
float GetHP() const {
return m_HP;
}
/**
* \brief Set the HP of the player
* \param hp The HP of the player
*/
void SetHP(float hp) {
m_HP = hp;
}
/**
* \brief When the player is a bot
* \return True if the player is a bot
*/
bool IsBot() const {
return m_IsBot;
}
/**
* \brief Set the player as a bot
*/
void SetBot() {
m_IsBot = true;
}
PlayerStats& GetStats() {
/**
* \brief Get the statistics of the player (const version)
* \return The statistics of the player
*/
const PlayerStats& GetStats() const {
return m_Stats;
}
void SetStats(const PlayerStats& stats) {
m_Stats = stats;
/**
* \brief Get the statistics of the player
* \return The statistics of the player
*/
PlayerStats& GetStats() {
return m_Stats;
}
};

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file Maths.h
* \brief File containing mathematical functions and constants
*/
#include "blitz/maths/Vector.h"
#include <cmath>
@@ -8,18 +13,19 @@ namespace maths {
static constexpr float PI = 3.141592653f;
template <typename T>
/**
* @brief returns the amount of overlap between the ranges [a1 ; b1] and [a2 ; b2]
*/
* \return the amount of overlap between the ranges [a1 ; b1] and [a2 ; b2]
*/
template <typename T>
T RangesOverlap(T& a1, T& b1, T& a2, T& b2) {
return std::min(std::max(a1, b1), std::max(a2, b2)) - std::max(std::min(a1, b1), std::min(a2, b2));
}
template <typename T>
/**
* @brief returns whether the ranges [a1 ; b1] and [a2 ; b2] overlap
*/
* \return whether the ranges [a1 ; b1] and [a2 ; b2] overlap
*/
template <typename T>
bool RangesOverlapping(T& a1, T& b1, T& a2, T& b2) {
return RangesOverlap(a1, a2, b1, b2) >= 0;
}
@@ -28,11 +34,19 @@ bool RangesOverlapping(T& a1, T& b1, T& a2, T& b2) {
// Vectors //
//////////////////////////////////////////////////////////////////
/**
* \brief Returns the length of the vector
* \return the length of the vector
*/
template <typename T>
T Length(const Vec3<T>& vect) {
return std::sqrt(vect.x * vect.x + vect.y * vect.y + vect.z * vect.z);
}
/**
* \brief Normalizes the vector
* \return the normalized vector
*/
template <typename T>
Vec3<T> Normalize(const Vec3<T>& vect) {
T length = Length(vect);
@@ -40,6 +54,10 @@ Vec3<T> Normalize(const Vec3<T>& vect) {
return {vect.x / length, vect.y / length, vect.z / length};
}
/**
* \brief Normalizes the vector
* \return the normalized vector
*/
template <typename T>
Vec4<T> Normalize(const Vec4<T>& vect) {
T length = std::sqrt(vect.x * vect.x + vect.y * vect.y + vect.z * vect.z + vect.w * vect.w);
@@ -47,11 +65,19 @@ Vec4<T> Normalize(const Vec4<T>& vect) {
return {vect.x / length, vect.y / length, vect.z / length, vect.w / length};
}
/**
* \brief Returns the dot product of the two vectors
* \return the dot product of the two vectors
*/
template <typename T>
T Dot(const Vec3<T>& vect, const Vec3<T>& other) {
return vect.x * other.x + vect.y * other.y + vect.z * other.z;
}
/**
* \brief Returns the cross product of the two vectors
* \return the cross product of the two vectors
*/
template <typename T>
Vec3<T> Cross(const Vec3<T>& vect, const Vec3<T>& other) {
return {
@@ -61,35 +87,46 @@ Vec3<T> Cross(const Vec3<T>& vect, const Vec3<T>& other) {
};
}
/**
* \brief Returns the dot product of the two vectors
* \return the dot product of the two vectors
*/
template <typename T>
T Dot(const Vec4<T>& vect, const Vec4<T>& other) {
return vect.x * other.x + vect.y * other.y + vect.z * other.z + vect.w * other.w;
}
/**
* \brief Returns the distance between the two vectors
* \return the distance between the two vectors
*/
template <typename T>
T Distance(const Vec3<T>& vect, const Vec3<T>& other) {
return Length(vect - other);
}
// it seems that `std::{min, max}`'s behavior conflicts with that of `cmath`'s `f{min, max}[f]`
// Why? Like I fucking know dude
/**
* \brief Returns the minimum of the three coordinates of the vector
* \return the minimum between the three coordinates of the vector
*/
template <typename T>
T ReduceMin(const Vec3<T>& vect) {
return std::min(std::min(vect.x, vect.y), vect.z);
}
/**
* \brief Returns the maximum of the three coordinates of the vector
* \return the maximum between the three coordinates of the vector
*/
template <typename T>
T ReduceMax(const Vec3<T>& vect) {
return std::max(std::max(vect.x, vect.y), vect.z);
}
/**
* @brief returns the (signed) minimal coordinate of the vector
*
* @param v
* @return constexpr T
* \brief Returns the (signed) minimal coordinate of the vector
* \param v a vector
* \return the (signed) minimal coordinate of the vector
*/
template <>
inline float ReduceMin<float>(const Vec3f& v) {
@@ -97,10 +134,9 @@ inline float ReduceMin<float>(const Vec3f& v) {
}
/**
* @brief returns the (signed) maximal coordinate of the vector
*
* @param v
* @return constexpr T
* \brief Returns the (signed) maximal coordinate of the vector
* \param v a vector
* \return the (signed) maximal coordinate of the vector
*/
template <>
inline float ReduceMax<float>(const Vec3f& v) {
@@ -108,10 +144,9 @@ inline float ReduceMax<float>(const Vec3f& v) {
}
/**
* @brief returns the (signed) minimal coordinate of the vector
*
* @param v
* @return constexpr T
* \brief returns the (signed) minimal coordinate of the vector
* \param v a vector
* \return the (signed) minimal coordinate of the vector
*/
template <>
inline double ReduceMin<double>(const Vec3d& v) {
@@ -119,10 +154,9 @@ inline double ReduceMin<double>(const Vec3d& v) {
}
/**
* @brief returns the (signed) maximal coordinate of the vector
*
* @param v
* @return constexpr T
* \brief returns the (signed) maximal coordinate of the vector
* \param v a vector
* \return the (signed) maximal coordinate of the vector
*/
template <>
inline double ReduceMax<double>(const Vec3d& v) {
@@ -130,13 +164,13 @@ inline double ReduceMax<double>(const Vec3d& v) {
}
/**
* @brief returns the coordinate-wise minimum of the given vectors,
* where a coordinate in the returned vector is NAN iff any of the two compared ones are NAN
*
* @tparam T
* @param self
* @param other
* @return constexpr Vec3f
* \brief returns the coordinate-wise minimum of the given vectors, where a coordinate in the returned vector is NAN iff any of the two
* compared ones are NAN
* \tparam T
* \param self a vector
* \param other an other vector
* \return the coordinate-wise minimum of the given vectors, where a coordinate in the returned vector is NAN iff any of the two
* compared ones are NAN
*/
template <typename T>
constexpr Vec3<T> Min(const Vec3<T>& self, const Vec3<T>& other) {
@@ -148,13 +182,13 @@ constexpr Vec3<T> Min(const Vec3<T>& self, const Vec3<T>& other) {
}
/**
* @brief returns the coordinate-wise maximum of the given vectors,
* \brief returns the coordinate-wise maximum of the given vectors,
* where a coordinate in the returned vector is NAN iff any of the two compared ones are NAN
* \tparam T
* \param self a vector
* \param other an other vector
* \return returns the coordinate-wise maximum of the given vectors,
* where a coordinate in the returned vector is NAN iff any of the two compared ones are NAN
*
* @tparam T
* @param self
* @param other
* @return constexpr Vec3f
*/
template <typename T>
constexpr Vec3<T> Max(const Vec3<T>& self, const Vec3<T>& other) {
@@ -169,6 +203,10 @@ constexpr Vec3<T> Max(const Vec3<T>& self, const Vec3<T>& other) {
// Matricies //
//////////////////////////////////////////////////////////////////
/**
* \brief Returns the dot product of the matrix and the vector
* \return the dot product of the matrix and the vector
*/
template <typename T>
Vec4<T> Dot(const Mat4<T>& mat, const Vec4<T>& vect) {
return {mat.x0 * vect.x + mat.x1 * vect.y + mat.x2 * vect.z + mat.x3 * vect.w,
@@ -177,6 +215,10 @@ Vec4<T> Dot(const Mat4<T>& mat, const Vec4<T>& vect) {
mat.w0 * vect.x + mat.w1 * vect.y + mat.w2 * vect.z + mat.w3 * vect.w};
}
/**
* \brief Returns the dot product of the matrix and an other matrix
* \return the dot product of the matrix and the other matrix
*/
template <typename T>
Mat4<T> Dot(const Mat4<T>& mat, const Mat4<T>& other) {
Mat4<T> result{};
@@ -192,6 +234,10 @@ Mat4<T> Dot(const Mat4<T>& mat, const Mat4<T>& other) {
return result;
}
/**
* \brief Returns the identity matrix
* \return the identity matrix
*/
template <typename T>
Mat4<T> Identity() {
Mat4<T> result{};
@@ -204,6 +250,10 @@ Mat4<T> Identity() {
return result;
}
/**
* \brief Returns the transposed matrix
* \return the transposed matrix
*/
template <typename T>
Mat4<T> Transpose(const Mat4<T>& mat) {
Mat4<T> result;
@@ -228,22 +278,88 @@ Mat4<T> Transpose(const Mat4<T>& mat) {
return result;
}
/**
* \brief Returns the perspective matrix
* \param fovY The field of view in the y direction
* \param aspectRatio The aspect ratio of the screen
* \param zNear The near clipping plane
* \param zFar The far clipping plane
* \return the perspective matrix
*/
Mat4f Perspective(float fovY, float aspectRatio, float zNear, float zFar);
/**
* \brief Returns the look matrix
* \param eyePos The position of the camera
* \param front The front vector of the camera
* \param up The up vector of the camera
* \return the look matrix
*/
Mat4f Look(const Vec3f& eyePos, const Vec3f& front, const Vec3f& up);
/**
* \brief Returns the inverse of the matrix
* \return the inverse of the matrix
*/
Mat4f Inverse(const Mat4f& mat);
/**
* \brief Returns the translation matrix
* \param translation The translation vector
* \return the translation matrix
*/
Mat4f Translate(const Vec3f& translation);
/**
* \brief Returns the scale matrix
* \param axisFactor The scaling factor for each axis
* \return the scale matrix
*/
Mat4f Scale(const Vec3f& axisFactor);
/**
* \brief Returns the rotation matrix around the x axis
* \param angle The angle of rotation
* \return the rotation matrix
*/
Mat4f RotateX(float angle);
/**
* \brief Returns the rotation matrix around the y axis
* \param angle The angle of rotation
* \return the rotation matrix
*/
Mat4f RotateY(float angle);
/**
* \brief Returns the rotation matrix around the z axis
* \param angle The angle of rotation
* \return the rotation matrix
*/
Mat4f RotateZ(float angle);
/**
* \brief Returns the rotation matrix
* \param angles The angles of rotation
* \return the rotation matrix
*/
Mat4f Rotate(const Vec3f& angles);
/**
* \brief Returns the rotation matrix
* \param angle The angle of rotation
* \param axis The axis of rotation
* \return the rotation matrix
*/
Mat4f Rotate(float angle, Vec3f axis);
/**
* \brief Returns the unit vector correspond to the yaw and pitch
* \param yaw Angle in radians
* \param pitch Angle in radians
*/
Vec3f GetDirectionVectorFromRotation(float yaw, float pitch);
} // namespace maths
} // namespace blitz

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file Vector.h
* \brief File containing the Vector structs and 4x4 matrix
*/
#include <algorithm>
#include <cmath>
#include <cstddef>

View File

@@ -1,63 +1,88 @@
#pragma once
/**
* \file Easing.h
* \brief File containing mathematical functions and constants
*/
namespace blitz {
namespace utils {
/* Sine functions */
/**
* \brief Sine functions
*/
float EaseInSine(float x);
float EaseOutSine(float x);
float EaseInOutSine(float x);
/* Cubic functions */
/**
* \brief Cubic functions
*/
float EaseInCubic(float x);
float EaseOutCubic(float x);
float EaseInOutCubic(float x);
/* Quint functions */
/**
* \brief Quint functions
*/
float EaseInQuint(float x);
float EaseOutQuint(float x);
float EaseInOutQuint(float x);
/* Circ functions */
/**
* \brief Circ functions
*/
float EaseInCirc(float x);
float EaseOutCirc(float x);
float EaseInOutCirc(float x);
/* Elastic functions */
/**
* \brief Elastic functions
*/
float EaseInElastic(float x);
float EaseOutElastic(float x);
float EaseInOutElastic(float x);
/* Quad functions */
/**
* \brief Quad functions
*/
float EaseInQuad(float x);
float EaseOutQuad(float x);
float EaseInOutQuad(float x);
/* Quart functions */
/**
* \brief Quart functions
*/
float EaseInQuart(float x);
float EaseOutQuart(float x);
float EaseInOutQuart(float x);
/* Expo functions */
/**
* \brief Expo functions
*/
float EaseInExpo(float x);
float EaseOutExpo(float x);
float EaseInOutExpo(float x);
/* Back functions */
/**
* \brief Back functions
*/
float EaseInBack(float x);
float EaseOutBack(float x);
float EaseInOutBack(float x);
/* Bounce functions */
/**
* \brief Bounce functions
*/
float EaseInBounce(float x);
float EaseOutBounce(float x);

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file Format.h
* \brief This file contains the definition of the `Format` function.
*/
#include <memory>
#include <stdexcept>
#include <string>
@@ -7,6 +12,17 @@
namespace blitz {
namespace utils {
/**
* \brief Formats a string using a format string and variadic arguments.
*
* This function takes a format string and a variable number of arguments and returns a formatted string.
* The format string can contain placeholders that will be replaced by the corresponding arguments.
*
* \param format The format string.
* \param args The variadic arguments to be formatted.
* \return The formatted string.
* \throws std::runtime_error if an error occurs during formatting.
*/
template <typename... Args>
std::string Format(const std::string& format, Args... args) {
int size = snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'

View File

@@ -1,13 +1,32 @@
#pragma once
/**
* \file Log.h
* \brief File defining log functions
*/
#include <string>
namespace blitz {
namespace utils {
void LOG(const std::string& msg); // Normal
void LOGD(const std::string& msg); // Normal en mode debug
void LOGE(const std::string& err); // Normal erreur
/**
* \brief Logs a normal message.
* \param msg The message to be logged.
*/
void LOG(const std::string& msg);
/**
* \brief Logs a normal message in debug mode.
* \param msg The message to be logged.
*/
void LOGD(const std::string& msg);
/**
* \brief Logs an error message.
* \param err The error message to be logged.
*/
void LOGE(const std::string& err);
} // namespace utils
} // namespace blitz

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file ObjectNotifier.h
* \brief File containing the blitz::ObjectNotifier class
*/
#include <algorithm>
#include <functional>
#include <vector>
@@ -7,16 +12,26 @@
namespace blitz {
namespace utils {
/**
* \class ObjectNotifier
* \brief Class used to notify listeners
*/
template <typename Listener>
class ObjectNotifier {
protected:
std::vector<Listener*> m_Listeners;
public:
/**
* \brief Binds a listener to notify later
*/
void BindListener(Listener* listener) {
m_Listeners.push_back(listener);
}
/**
* \brief Unbinds a listener (in case the listener is destroyed for example)
*/
void UnbindListener(Listener* listener) {
auto iter = std::find(m_Listeners.begin(), m_Listeners.end(), listener);
@@ -26,8 +41,11 @@ class ObjectNotifier {
m_Listeners.erase(iter);
}
/**
* \brief Notify listeners that were bound
*/
template <typename Func, typename... Args>
void NotifyListeners(Func function, Args... args) {
void NotifyListeners(Func function, Args... args) const {
for (Listener* listener : m_Listeners)
std::bind(function, listener, args...)();
}

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file PrettyLog.h
* \brief File defining log functions with colors
*/
#include "blitz/maths/Vector.h"
#include <string>
@@ -18,7 +23,13 @@ const static Vec3uc YELLOW = {255, 255, 0};
} // namespace TextColor
/**
* \brief Returns the color code for a given color.
*/
std::string GetTextColor(Vec3uc color);
/**
* \brief Returns the color code for the reset color.
*/
std::string GetTextColorReset();
} // namespace utils

View File

@@ -1,10 +1,21 @@
#pragma once
/**
* \file Random.h
* \brief Defines functions for generating random numbers.
*/
#include <random>
namespace blitz {
namespace utils {
/**
* \brief Returns a random integer between min and max.
* \param min The minimum value.
* \param max The maximum value.
* \return A random integer between min and max.
*/
template <typename NumberType>
NumberType GetRandomInt(NumberType min, NumberType max) {
std::random_device randomDevice;
@@ -13,6 +24,12 @@ NumberType GetRandomInt(NumberType min, NumberType max) {
return distrib(generator);
}
/**
* \brief Returns a random real number between min and max.
* \param min The minimum value.
* \param max The maximum value.
* \return A random real number between min and max.
*/
template <typename NumberType>
NumberType GetRandomReal(NumberType min, NumberType max) {
std::random_device randomDevice;

View File

@@ -10,7 +10,16 @@
namespace blitz {
namespace utils {
/**
* \def BLITZ_TEST_SUCCESSFUL
* \brief Used in tests to indicate that a test was successful
*/
#define BLITZ_TEST_SUCCESSFUL 0
/**
* \def BLITZ_TEST_FAILED
* \brief Used in tests to indicate that a test failed
*/
#define BLITZ_TEST_FAILED 1
#ifndef __FUNCTION_NAME__
@@ -24,7 +33,8 @@ namespace utils {
/**
* \def blitz_test_assert
* \param ... The expression to evaluate
* \brief Evaluates the expression and exits the program if not valid
* \brief Evaluates the expression and exits the program if not valid.
* \note It works like a basic assert() but also in release mode
*/
#define blitz_test_assert(...) \
if (!static_cast<bool>(__VA_ARGS__)) { \
@@ -37,6 +47,7 @@ namespace utils {
* \def blitz_debug_assert
* \param ... The expression to execute
* \brief Assertion without checks in release mode
* \note The expression is always executed. However, in release, no checks are made !
*/
#ifdef NDEBUG
#define blitz_debug_assert(...) __VA_ARGS__

View File

@@ -1,10 +1,19 @@
#pragma once
/**
* \file TickCounter.h
* \brief File containing the blitz::utils::TickCounter class
*/
#include <cstdint>
namespace blitz {
namespace utils {
/**
* \class TickCounter
* \brief Class used to count ticks
*/
class TickCounter {
private:
float m_TPS;
@@ -14,19 +23,42 @@ class TickCounter {
int m_TargetTPS;
public:
/**
* \brief Constructor
* \param tps The target ticks per second
*/
TickCounter(int tps) : m_TargetTPS(tps) {}
/**
* \brief Reset the tick counter
*/
void Reset();
bool Update(); // return true when tps is updated
/**
* \brief Update the tick counter
* \return True if the tick counter has been updated
*/
bool Update();
/**
* \brief Get the ticks per second
* \return The ticks per second
*/
float GetTPS() const {
return m_TPS;
}
/**
* \brief Get the milliseconds per tick
* \return The milliseconds per tick
*/
float GetMSPT() const {
return m_MSPT;
}
/**
* \brief Set the ticks per second
* \param mspt The ticks per second
*/
void SetMSPT(float mspt) {
m_MSPT = mspt;
}

View File

@@ -1,16 +1,30 @@
#pragma once
/**
* \file Time.h
* \brief File containing the blitz::utils::AutoTimer, blitz::utils::Timer, blitz::utils::CooldownTimer and blitz::utils::DelayTimer
* classes
*/
#include <algorithm>
#include <cstdint>
#include <functional>
namespace blitz {
namespace utils {
/**
* \brief Get current time
* \return Time elapsed since epoch in milliseconds
*/
std::uint64_t GetTime();
typedef std::function<void()> TimerExecFunction;
// utililty class to call a function at regular period of time
/**
* \class AutoTimer
* \brief Calls a function at regular period of time
*/
class AutoTimer {
private:
std::uint64_t m_Interval;
@@ -20,65 +34,136 @@ class AutoTimer {
std::uint64_t m_InternalTime = 0;
public:
/**
* \brief Default constructor
*/
AutoTimer() : m_Interval(0), m_Function(nullptr) {}
/**
* \param interval Time between each function call in milliseconds
*/
AutoTimer(std::uint64_t interval) : m_Interval(interval), m_Function(nullptr) {}
/**
* \param interval Time between each function call in milliseconds
* \param callback The function to call peridocally
*/
AutoTimer(std::uint64_t interval, TimerExecFunction callback) : m_Interval(interval), m_Function(callback) {}
/**
* \brief Updates the timer
*/
void Update();
/**
* \brief Updates the timer with the desired time step
* \param delta The time step in milliseconds
*/
void Update(std::uint64_t delta);
/**
* \brief Resets the internal cooldown
*/
void Reset();
/**
* \brief Sets a new interval
* \param newInterval the new interval in milliseconds
*/
void SetInterval(std::uint64_t newInterval) {
m_Interval = newInterval;
}
/**
* \return The interval between each callback in milliseconds
*/
std::uint64_t GetInterval() const {
return m_Interval;
}
/**
* \brief Set a new callback function
* \param newCallback The function to call
*/
void SetCallbackFunction(TimerExecFunction newCallback) {
m_Function = newCallback;
}
/**
* \return The callback function
*/
TimerExecFunction GetCallbackFunction() const {
return m_Function;
}
};
// utililty class to trigger update at regular period of time
/**
* \class Timer
* \brief Utililty class to trigger update at regular period of time
*/
class Timer {
private:
std::uint64_t m_Interval; // in millis
std::uint64_t m_InternalTime = 0;
public:
/**
* \brief Default constructor
*/
Timer() : m_Interval(0) {}
/**
* \brief Construct a Timer with the desired interval
* \param interval The interval between each update in milliseconds
*/
Timer(std::uint64_t interval) : m_Interval(interval) {}
/**
* \brief Updates the timer
* \param delta The time step in milliseconds
* \return true every interval milliseconds
*/
bool Update(std::uint64_t delta);
/**
* \brief Resets the timer to its original state
*/
void Reset();
// void ResetSoft(); // don't trigger the timer
/**
* \return The time remaing before the next Update() call will return true (in milliseconds)
*/
std::uint64_t GetTimeRemaining() const {
return m_Interval - m_InternalTime;
}
/**
* \return The time elapsed since the previous Update() call returned true (in milliseconds)
*/
std::uint64_t GetTimeElapsed() const {
return m_InternalTime;
}
/**
* \brief Set a new value for the interval
* \param newInterval the new interval to set
*/
void SetInterval(std::uint64_t newInterval) {
m_Interval = newInterval;
}
/**
* \return The interval between each successful Update()
*/
std::uint64_t GetInterval() const {
return m_Interval;
}
};
// utililty class to trigger update at regular period of time with a cooldown
/**
* \class CooldownTimer
* \brief Class to trigger update at regular period of time with a cooldown
*/
template <typename T>
class CooldownTimer {
private:
@@ -86,9 +171,20 @@ class CooldownTimer {
T m_CooldownTime;
public:
/**
* \brief Default constructor
*/
CooldownTimer() : m_Cooldown(0), m_CooldownTime(0) {}
/**
* \param cooldown The cooldown before Update() returns true again
*/
CooldownTimer(T cooldown) : m_Cooldown(0), m_CooldownTime(cooldown) {}
/**
* \brief Update the timer
* \param delta the time step
*/
bool Update(T delta) {
if (m_Cooldown > 0) {
m_Cooldown = std::max<T>(static_cast<T>(0), static_cast<T>(m_Cooldown - delta));
@@ -96,24 +192,40 @@ class CooldownTimer {
return m_Cooldown == 0;
}
/**
* \brief Apply a cooldown for the timer
*/
void ApplyCooldown() {
m_Cooldown = m_CooldownTime;
}
/**
* \brief Reset the cooldown. Update() will return true immediatly afterward.
*/
void Reset() {
m_Cooldown = 0;
}
/**
* \brief Change the timer cooldown
* \param newCooldown the new cooldown
*/
void SetCooldown(T newCooldown) {
m_CooldownTime = newCooldown;
}
/**
* \return The cooldown of the timer
*/
T GetCooldown() const {
return m_CooldownTime;
}
};
// utililty class to trigger update at regular period of time with a cooldown
/**
* \class DelayTimer
* \brief class to trigger an update after a period of time
*/
template <typename T>
class DelayTimer {
private:
@@ -121,7 +233,14 @@ class DelayTimer {
T m_InternalTime;
public:
/**
* \brief Default constructor
*/
DelayTimer() : m_DelayTime(0), m_InternalTime(0) {}
/**
* \param delay The delay to set
*/
DelayTimer(T delay) : m_DelayTime(delay), m_InternalTime(delay) {}
/**
@@ -133,16 +252,23 @@ class DelayTimer {
}
/**
* \brief Resets the timer
* \brief Resets the timer. Update() will immediatly return true
*/
void Reset() {
m_InternalTime = m_DelayTime;
}
/**
* \brief Changes the delay of the timer
* \param newDelay the new delay
*/
void SetDelay(T newDelay) {
m_DelayTime = newDelay;
}
/**
* \return the delay of the timer
*/
T GetDelay() const {
return m_DelayTime;
}

View File

@@ -41,28 +41,28 @@ class Connexion : public protocol::PacketHandler, private NonCopyable {
/**
* \brief Default destructor
*/
*/
virtual ~Connexion();
/**
* \brief Reads socket and process a Packet, if any
*/
* \brief Reads socket and process a Packet, if any
*/
virtual bool UpdateSocket();
/**
* \brief Closes the connexion
*/
*/
void CloseConnection();
/**
* \brief Tries to connect the socket at the specified address and port
* \return Wether this action was succesfull
*/
virtual bool Connect(const std::string& address, std::uint16_t port);
* \return Whether this action was succesfull
*/
bool Connect(const std::string& address, std::uint16_t port);
/**
* \brief Returns the TCPSocket::Status of the internal socket
*/
*/
TCPSocket::Status GetSocketStatus() const {
return m_Socket.GetStatus();
}
@@ -70,7 +70,7 @@ class Connexion : public protocol::PacketHandler, private NonCopyable {
/**
* \brief Sends the protocol::Packet over the network to the remote
* \param packet The protocol::Packet to send
*/
*/
void SendPacket(const protocol::Packet* packet);
};

View File

@@ -35,7 +35,7 @@ class TCPListener : private NonCopyable {
* \param port The port to listen to
* \param maxConnexions The maximum amount of connexion that can happen at the same time. \n
* Every other guests will be kicked if this amount is reached.
* \return Wether this action was succesfull
* \return Whether this action was succesfull
*/
bool Listen(std::uint16_t port, int maxConnexions);

View File

@@ -1,5 +1,11 @@
#pragma once
/**
* \file PacketDispatcher.h
* \brief File containing the blitz::protocol::PacketDispatcher class
*/
#include "blitz/common/NonCopyable.h"
#include "blitz/protocol/Protocol.h"
#include <map>
@@ -9,22 +15,42 @@ namespace protocol {
class PacketHandler;
class PacketDispatcher {
/**
* \class PacketDispatcher
* \brief Class used to dispatch packets
*/
class PacketDispatcher : private NonCopyable {
private:
std::map<PacketType, std::vector<PacketHandler*>> m_Handlers;
public:
PacketDispatcher() = default;
PacketDispatcher(const PacketDispatcher& rhs) = delete;
PacketDispatcher& operator=(const PacketDispatcher& rhs) = delete;
PacketDispatcher(PacketDispatcher&& rhs) = delete;
PacketDispatcher& operator=(PacketDispatcher&& rhs) = delete;
/**
* \brief Constructor
*/
PacketDispatcher() {}
/**
* \brief Dispatch a packet
* \param packet The packet to dispatch
*/
void Dispatch(const Packet* packet);
/**
* \brief Register a packet handler
* \param type The packet type
* \param handler The packet handler
*/
void RegisterHandler(PacketType type, PacketHandler* handler);
/**
* \brief Unregister a packet handler
* \param type The packet type
* \param handler The packet handler
*/
void UnregisterHandler(PacketType type, PacketHandler* handler);
/**
* \brief Unregister a packet handler
* \param handler The packet handler
*/
void UnregisterHandler(PacketHandler* handler);
};

View File

@@ -1,13 +1,22 @@
#pragma once
/**
* \file PacketFactory.h
*/
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
namespace PacketFactory {
/**
* \brief Creates a packet from a buffer.
* \param buffer The buffer containing the packet data.
* \return The created packet.
*/
const Packet* CreatePacket(PacketType type, DataBuffer& buffer);
}
} // namespace PacketFactory
} // namespace protocol
} // namespace blitz

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file PacketHandler.h
* \brief File containing the blitz::protocol::PacketHandler class
*/
#include "blitz/protocol/PacketsForward.h"
#include "blitz/protocol/Protocol.h"
@@ -8,14 +13,26 @@ namespace protocol {
class PacketDispatcher;
/**
* \class PacketHandler
* \brief Class used to handle packets
*/
class PacketHandler {
private:
PacketDispatcher* m_Dispatcher;
public:
/**
* \brief Constructor
* \param dispatcher The packet dispatcher
*/
PacketHandler(PacketDispatcher* dispatcher) : m_Dispatcher(dispatcher) {}
virtual ~PacketHandler() {}
/**
* \brief Get the packet dispatcher
* \return The packet dispatcher
*/
PacketDispatcher* GetDispatcher() {
return m_Dispatcher;
}
@@ -31,6 +48,7 @@ class PacketHandler {
virtual void HandlePacket(const PlayerPositionAndRotationPacket* packet) {}
virtual void HandlePacket(const PlayerShootPacket* packet) {}
virtual void HandlePacket(const PlayerStatsPacket* packet) {}
virtual void HandlePacket(const ServerConfigPacket* packet) {}
virtual void HandlePacket(const ServerTpsPacket* packet) {}
virtual void HandlePacket(const UpdateGameStatePacket* packet) {}
virtual void HandlePacket(const UpdateHealthPacket* packet) {}

View File

@@ -9,6 +9,7 @@
#include "packets/PlayerPositionAndRotationPacket.h"
#include "packets/PlayerShootPacket.h"
#include "packets/PlayerStatsPacket.h"
#include "packets/ServerConfigPacket.h"
#include "packets/ServerTpsPacket.h"
#include "packets/UpdateGameStatePacket.h"
#include "packets/UpdateHealthPacket.h"

View File

@@ -14,6 +14,7 @@ class PlayerLoginPacket;
class PlayerPositionAndRotationPacket;
class PlayerShootPacket;
class PlayerStatsPacket;
class ServerConfigPacket;
class ServerTpsPacket;
class UpdateGameStatePacket;
class UpdateHealthPacket;

View File

@@ -2,7 +2,7 @@
/**
* \file Protocol.h
* \brief File describing protocol
* \brief File containing the blitz::protocol::Protocol class
*/
#include "blitz/common/DataBuffer.h"
@@ -29,6 +29,7 @@ enum class PacketType : std::uint8_t {
PlayerLeave, /**< Corresponds to PlayerLeavePacket */
PlayerList, /**< Corresponds to PlayerListPacket */
PlayerStats, /**< Corresponds to PlayerStatsPacket */
ServerConfig, /**< Corresponds to ServerConfigPacket*/
ServerTps, /**< Corresponds to ServerTpsPacket */
UpdateGameState, /**< Corresponds to UpdateGameStatePacket */

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file ChatPacket.h
* \brief File containing the blitz::protocol::ChatPacket class
*/
#include "blitz/maths/Vector.h"
#include "blitz/protocol/Protocol.h"
#include <vector>
@@ -7,20 +12,53 @@
namespace blitz {
namespace protocol {
/**
* \struct ColoredPart
* \brief Represents a part of a chat message with a specific color.
*/
struct ColoredPart {
/**
* \brief The color of the part.
*/
Vec4f color;
/**
* \brief The text of the part.
*/
std::string text;
};
typedef std::vector<ColoredPart> ColoredText;
/**
* \class ChatPacket
* \brief Packet for sending chat messages.
* %Packet structure :
* | PacketType |
* |------------------------|
* | PacketType::Chat |
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|-------------------------------|
* | m_Message | ColoredText | The message sent in the chat |
*/
class ChatPacket : public Packet {
private:
ColoredText m_Message;
public:
/**
* \brief Default constructor.
*/
ChatPacket() {}
/**
* \brief Constructor.
* \param msg The message to send.
*/
ChatPacket(const std::string& msg) : m_Message(ColorizeText(msg)) {}
/**
* \brief Constructor.
* \param msg The message to send.
*/
ChatPacket(const ColoredText& msg) : m_Message(msg) {}
virtual ~ChatPacket() {}
@@ -28,6 +66,10 @@ class ChatPacket : public Packet {
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Get the message.
* \return The message.
*/
const ColoredText& GetMessage() const {
return m_Message;
}
@@ -36,8 +78,17 @@ class ChatPacket : public Packet {
return PacketType::Chat;
}
/**
* \brief Get the text color.
*/
static std::string GetTextColor(Vec3uc color);
/**
* \brief Colorize a text.
*/
static ColoredText ColorizeText(const std::string& text);
/**
* \brief Get the colored text string.
*/
static std::string GetColoredTextString(const ColoredText& text);
};

View File

@@ -1,16 +1,40 @@
#pragma once
/**
* \file ConnexionInfoPacket.h
* \brief File containing the blitz::protocol::ConnexionInfoPacket class
*/
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
/**
* \class ConnexionInfoPacket
* \brief Packet for sending connection information.
* %Packet structure :
* | PacketType |
* |------------------------|
* | PacketType::ConnexionInfo |
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|-------------------------------|
* | m_ConnectionID | std::uint8_t | The connection ID |
*/
class ConnexionInfoPacket : public Packet {
private:
std::uint8_t m_ConnectionID;
public:
/**
* \brief Default constructor.
*/
ConnexionInfoPacket() {}
/**
* \brief Constructor.
* \param connectionID The ID of the connection.
*/
ConnexionInfoPacket(std::uint8_t connectionID) : m_ConnectionID(connectionID) {}
virtual ~ConnexionInfoPacket() {}
@@ -18,6 +42,10 @@ class ConnexionInfoPacket : public Packet {
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Get the connection ID.
* \return The connection ID.
*/
std::uint8_t GetConnectionID() const {
return m_ConnectionID;
}

View File

@@ -1,15 +1,39 @@
#pragma once
/**
* \file DisconnectPacket.h
* \brief File containing the blitz::protocol::DisconnectPacket class
*/
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
/**
* \class DisconnectPacket
* \brief Packet for disconnecting from the server.
* %Packet structure :
* | PacketType |
* |------------------------|
* | PacketType::Disconnect |
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|-------------------------------|
* | m_Reason | std::string | The reason for disconnection |
*/
class DisconnectPacket : public Packet {
private:
std::string m_Reason; // only when sent from server
public:
/**
* \brief Default constructor.
*/
DisconnectPacket() {}
/**
* \brief Constructor.
* \param reason The reason for disconnection.
*/
DisconnectPacket(std::string reason) : m_Reason(reason) {}
virtual ~DisconnectPacket() {}
@@ -17,6 +41,10 @@ class DisconnectPacket : public Packet {
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Get the reason for disconnection.
* \return The reason for disconnection.
*/
const std::string& GetReason() const {
return m_Reason;
}

View File

@@ -13,14 +13,14 @@ namespace protocol {
/**
* \class KeepAlivePacket
* \brief %Packet sent to measure the health of a connexion. \n
* \brief Packet sent to measure the health of a connexion. \n
* The client must respond with the same alive ID. Else, the connexion will be closed. \n
* %Packet structure :
* %Packet structure :
* | PacketType |
* |------------------------|
* | PacketType::KeepAlive |
*
* | Field Name | Field Type | Notes |
*
* | Field Name | Field Type | Notes |
* |--------------------|---------------|---------------------------------------------------------------------------|
* | Keep Alive ID | VarInt | The server generates a random ID, the client must respond with the same |
*

View File

@@ -13,7 +13,7 @@ namespace protocol {
/**
* \class PlayerJoinPacket
* \brief %Packet sent when a new player joins the game \n
* \brief Packet sent when a new player joins the game
* %Packet structure :
* | PacketType |
* |------------------------|

View File

@@ -1,24 +1,53 @@
#pragma once
/**
* \file PlayerLeavePacket.h
* \brief File containing the blitz::protocol::PlayerLeavePacket class
*/
#include "blitz/common/Defines.h"
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
/**
* \class PlayerLeavePacket
* \brief Packet for when a player leaves the game.
* %Packet structure :
* | PacketType |
* |------------------------|
* | PacketType::PlayerLeave|
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|-------------------------------|
* | m_PlayerID | PlayerID |The ID of the player that left |
*/
class PlayerLeavePacket : public Packet {
private:
std::uint8_t m_PlayerID;
game::PlayerID m_PlayerID;
public:
/**
* \brief Default constructor.
*/
PlayerLeavePacket() {}
PlayerLeavePacket(std::uint8_t playerID) : m_PlayerID(playerID) {}
/**
* \brief Constructor.
* \param playerID The ID of the player that left.
*/
PlayerLeavePacket(game::PlayerID playerID) : m_PlayerID(playerID) {}
virtual ~PlayerLeavePacket() {}
virtual DataBuffer Serialize(bool packetID = true) const;
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
std::uint8_t GetPlayerID() const {
/**
* \brief Get the ID of the player that left.
* \return The ID of the player that left.
*/
game::PlayerID GetPlayerID() const {
return m_PlayerID;
}

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file PlayerListPacket.h
* \brief File containing the blitz::protocol::PlayerListPacket class
*/
#include <map>
#include "blitz/protocol/Protocol.h"
@@ -7,18 +12,34 @@
namespace blitz {
namespace protocol {
/**
* \struct PlayerInfo
* \brief Represents information about a player.
*/
struct PlayerInfo {
std::string name;
};
typedef std::map<std::uint8_t, PlayerInfo> PlayerList;
/**
* \class PlayerListPacket
* \brief Packet for sending the list of players.
* \todo PACKET STRUCTURE
*/
class PlayerListPacket : public Packet {
private:
PlayerList m_Players;
public:
/**
* \brief Default constructor.
*/
PlayerListPacket() {}
/**
* \brief Constructor.
* \param players The list of players.
*/
PlayerListPacket(const PlayerList& players) : m_Players(players) {}
virtual ~PlayerListPacket() {}
@@ -26,6 +47,11 @@ class PlayerListPacket : public Packet {
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Get the list of players.
* \return The list of players.
*/
const PlayerList& GetPlayers() const {
return m_Players;
}

View File

@@ -1,16 +1,40 @@
#pragma once
/**
* \file PlayerLoginPacket.h
* \brief File containing the blitz::protocol::PlayerLoginPacket class
*/
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
/**
* \class PlayerLoginPacket
* \brief Packet for when a player logs in.
* %Packet structure :
* | PacketType |
* |------------------------|
* | PacketType::PlayerLogin|
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|----------------------------------|
* | Player Name | std::string | Name of the player that logged in|
*/
class PlayerLoginPacket : public Packet {
private:
std::string m_PlayerName;
public:
/**
* \brief Default constructor.
*/
PlayerLoginPacket() {}
/**
* \brief Constructor.
* \param playerName The name of the player that logged in.
*/
PlayerLoginPacket(std::string playerName) : m_PlayerName(playerName) {}
virtual ~PlayerLoginPacket() {}
@@ -18,13 +42,17 @@ class PlayerLoginPacket : public Packet {
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
virtual PacketType GetType() const {
return PacketType::PlayerLogin;
}
/**
* \brief Get the name of the player that logged in.
* \return The name of the player that logged in.
*/
const std::string& GetPlayerName() const {
return m_PlayerName;
}
virtual PacketType GetType() const {
return PacketType::PlayerLogin;
}
};
} // namespace protocol

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file PlayerPositionAndRotationPacket.h
* \brief File containing the blitz::protocol::PlayerPositionAndRotationPacket class
*/
#include "blitz/common/Defines.h"
#include "blitz/maths/Vector.h"
#include "blitz/protocol/Protocol.h"
@@ -7,6 +12,21 @@
namespace blitz {
namespace protocol {
/**
* \class PlayerPositionAndRotationPacket
* \brief Packet for sending a player's position and rotation.
* %Packet structure :
* | PacketType |
* |--------------------------------|
* | PacketType::PlayerPositionAndRotation |
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|----------------------------------|
* | Player ID | PlayerID | Id of the player who moved |
* | Position | Vec3f | Position of the player |
* | Yaw | float | Yaw of the player |
* | Pitch | float | Pitch of the player |
*/
class PlayerPositionAndRotationPacket : public Packet {
private:
game::PlayerID m_Player; // only used when sent to client
@@ -14,28 +34,53 @@ class PlayerPositionAndRotationPacket : public Packet {
float m_Yaw, m_Pitch;
public:
/**
* \brief Default constructor.
*/
PlayerPositionAndRotationPacket() {}
/**
* \brief Constructor.
* \param position The position of the player.
* \param yaw The yaw of the player.
* \param pitch The pitch of the player.
* \param player The ID of the player.
*/
PlayerPositionAndRotationPacket(const Vec3f& position, float yaw, float pitch, game::PlayerID player = 0) :
m_Player(player), m_Position(position), m_Yaw(yaw), m_Pitch(pitch) {}
virtual ~PlayerPositionAndRotationPacket() {}
virtual DataBuffer Serialize(bool packetID = true) const;
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Get the position of the player.
* \return The position of the player.
*/
const Vec3f& GetPosition() const {
return m_Position;
}
/**
* \brief Get the yaw of the player.
* \return The yaw of the player.
*/
float GetYaw() const {
return m_Yaw;
}
/**
* \brief Get the pitch of the player.
* \return The pitch of the player.
*/
float GetPitch() const {
return m_Pitch;
}
/**
* \brief Get the ID of the player.
* \return The ID of the player.
*/
game::PlayerID GetPlayer() const {
return m_Player;
}

View File

@@ -1,11 +1,31 @@
#pragma once
/**
* \file PlayerShootPacket.h
* \brief File containing the blitz::protocol::PlayerShootPacket class
*/
#include "blitz/game/Player.h"
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
/**
* \class PlayerShootPacket
* \brief Packet for when a player shoots.
* %Packet structure :
* | PacketType |
* |------------------------|
* | PacketType::PlayerShoot|
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|----------------------------------|
* | Player ID | PlayerID | The ID of the player that shot |
* | Position | Vec3f | Position of the player |
* | Yaw | float | Yaw of the player |
* | Pitch | float | Pitch of the player |
*/
class PlayerShootPacket : public Packet {
private:
game::PlayerID m_Player; // only used when sent to client
@@ -13,7 +33,17 @@ class PlayerShootPacket : public Packet {
float m_Yaw, m_Pitch;
public:
/**
* \brief Default constructor.
*/
PlayerShootPacket() {}
/**
* \brief Constructor.
* \param position The position of the player.
* \param yaw The yaw of the player.
* \param pitch The pitch of the player.
* \param player The ID of the player.
*/
PlayerShootPacket(Vec3f position, float yaw, float pitch, game::PlayerID player = 0) :
m_Player(player), m_Position(position), m_Yaw(yaw), m_Pitch(pitch) {}
virtual ~PlayerShootPacket() {}
@@ -22,18 +52,34 @@ class PlayerShootPacket : public Packet {
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Get the position of the player.
* \return The position of the player.
*/
const Vec3f& GetPosition() const {
return m_Position;
}
/**
* \brief Get the yaw of the player.
* \return The yaw of the player.
*/
float GetYaw() const {
return m_Yaw;
}
/**
* \brief Get the pitch of the player.
* \return The pitch of the player.
*/
float GetPitch() const {
return m_Pitch;
}
/**
* \brief Get the ID of the player.
* \return The ID of the player.
*/
game::PlayerID GetPlayer() const {
return m_Player;
}

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file PlayerStatsPacket.h
* \brief File containing the blitz::protocol::PlayerStatsPacket class
*/
#include "blitz/common/Defines.h"
#include "blitz/game/Player.h"
#include "blitz/protocol/Protocol.h"
@@ -7,13 +12,34 @@
namespace blitz {
namespace protocol {
/**
* \class PlayerStatsPacket
* \brief Packet for sending player stats.
* %Packet structure :
* | PacketType |
* |------------------------|
* | PacketType::PlayerStats|
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|-------------------------------|
* | Player ID | PlayerID | Id of the player |
* | Player Stats | PlayerStats | Stats of the player |
*/
class PlayerStatsPacket : public Packet {
private:
game::PlayerID m_PlayerID;
game::PlayerStats m_PlayerStats;
public:
/**
* \brief Default constructor.
*/
PlayerStatsPacket() {}
/**
* \brief Constructor.
* \param playerID The ID of the player.
* \param stats The stats of the player.
*/
PlayerStatsPacket(game::PlayerID playerID, const game::PlayerStats& stats) : m_PlayerID(playerID), m_PlayerStats(stats) {}
virtual ~PlayerStatsPacket() {}

View File

@@ -0,0 +1,60 @@
#pragma once
/**
* \file ServerConfigPacket.h
* \brief File containing the blitz::protocol::ServerConfigPacket class
*/
#include "blitz/game/Game.h"
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
/**
* \class ServerConfigPacket
* \brief Packet for sending the server configuration.
* %Packet structure :
* | PacketType |
* |-------------------------|
* | PacketType::ServerConfig|
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|-------------------------------|
* | Game Config | GameConfig | The game configuration |
*/
class ServerConfigPacket : public Packet {
private:
game::GameConfig m_GameConfig;
public:
/**
* \brief Default constructor.
*/
ServerConfigPacket() {}
/**
* \brief Constructor.
* \param GameConfig The game configuration.
*/
ServerConfigPacket(const game::GameConfig& GameConfig) : m_GameConfig(GameConfig) {}
virtual ~ServerConfigPacket() {}
virtual DataBuffer Serialize(bool packetID = true) const;
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Getter of the game configuration
* \return The game configuration
*/
game::GameConfig GetGameConfig() const {
return m_GameConfig;
}
virtual PacketType GetType() const {
return PacketType::ServerConfig;
}
};
} // namespace protocol
} // namespace blitz

View File

@@ -1,17 +1,45 @@
#pragma once
/**
* \file ServerTpsPacket.h
* \brief File containing the blitz::protocol::ServerTpsPacket class
*/
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
/**
* \class ServerTpsPacket
* \brief Packet for sending server TPS (Tick per second) and MSPT (Milliseconds per tick).
* %Packet structure :
* | PacketType |
* |------------------------|
* | PacketType::ServerTps |
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|-------------------------------|
* | Tps | float | Server TPS |
* | Mspt | float | Server MSPT |
* | PacketSendTime | uint64_t | Time the packet was sent |
*/
class ServerTpsPacket : public Packet {
private:
float m_TPS;
float m_MSPT;
std::uint64_t m_PacketSendTime; // used to calculate ping
public:
/**
* \brief Default constructor.
*/
ServerTpsPacket() {}
/**
* \brief Constructor.
* \param tps The server TPS.
* \param mspt The server MSPT.
* \param sendTime The time the packet was sent.
*/
ServerTpsPacket(float tps, float mspt, std::uint64_t sendTime) : m_TPS(tps), m_MSPT(mspt), m_PacketSendTime(sendTime) {}
virtual ~ServerTpsPacket() {}
@@ -19,14 +47,27 @@ class ServerTpsPacket : public Packet {
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Get the server TPS.
* \return The server TPS.
*/
float GetTPS() const {
return m_TPS;
}
/**
* \brief Get the server MSPT.
* \return The server MSPT.
*/
float GetMSPT() const {
return m_MSPT;
}
/**
* \brief Get the time the packet was sent.
* \return The time the packet was sent.
* \todo Calculate ping.
*/
std::uint64_t GetPacketSendTime() const {
return m_PacketSendTime;
}

View File

@@ -1,18 +1,44 @@
#pragma once
/**
* \file UpdateGameStatePacket.h
* \brief File containing the blitz::protocol::UpdateGameStatePacket class
*/
#include "blitz/game/Game.h"
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
/**
* \class UpdateGameStatePacket
* \brief Packet for updating the game state.
* %Packet structure :
* | PacketType |
* |-----------------------------|
* | PacketType::UpdateGameState |
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|----------------------------------------------|
* | Game State | GameState | The new game state |
* | Time Remaining | std::uint64_t | The time remaining in the current game state |
*/
class UpdateGameStatePacket : public Packet {
private:
game::GameState m_GameState;
std::uint64_t m_TimeRemaining;
public:
/**
* \brief Default constructor.
*/
UpdateGameStatePacket() {}
/**
* \brief Constructor.
* \param a_GameState The new game state.
* \param a_TimeRemaining The time remaining in the current game state.
*/
UpdateGameStatePacket(game::GameState a_GameState, std::uint64_t a_TimeRemaining = 0) :
m_GameState(a_GameState), m_TimeRemaining(a_TimeRemaining) {}
virtual ~UpdateGameStatePacket() {}
@@ -21,10 +47,18 @@ class UpdateGameStatePacket : public Packet {
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Get the new game state.
* \return The new game state.
*/
game::GameState GetGameState() const {
return m_GameState;
}
/**
* \brief Get the time remaining in the current game state.
* \return The time remaining in the current game state.
*/
std::uint64_t GetTimeRemaining() const {
return m_TimeRemaining;
}

View File

@@ -1,16 +1,40 @@
#pragma once
/**
* \file UpdateHealthPacket.h
* \brief File containing the blitz::protocol::UpdateHealthPacket class
*/
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
/**
* \class UpdateHealthPacket
* \brief Packet for updating the health of a player.
* %Packet structure :
* | PacketType |
* |--------------------------|
* | PacketType::UpdateHealth |
*
* | Field Name | Field Type | Notes |
* |--------------------|-------------------|-------------------------------|
* | m_NewHealth | float | The new health value |
*/
class UpdateHealthPacket : public Packet {
private:
float m_NewHealth;
public:
/**
* \brief Default constructor.
*/
UpdateHealthPacket() {}
/**
* \brief Constructor.
* \param newHealth The new health value.
*/
UpdateHealthPacket(float newHealth) : m_NewHealth(newHealth) {}
virtual ~UpdateHealthPacket() {}
@@ -18,6 +42,10 @@ class UpdateHealthPacket : public Packet {
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
/**
* \brief Get the new health value.
* \return The new health value.
*/
float GetNewHealth() const {
return m_NewHealth;
}

View File

@@ -23,15 +23,10 @@ namespace server {
class Server;
} // namespace server
class GuiListener {
public:
virtual void OnTextChatReceived(const protocol::ColoredText& text) {}
virtual void OnSpectatorChange(game::PlayerID player) {}
virtual void OnPlayerShoot(game::PlayerID player, const Vec3f& position, float yaw, float pitch) {}
};
// Singleton
class Client : public utils::ObjectNotifier<GuiListener>, public game::PlayerInputListener {
class Client : public utils::ObjectNotifier<game::ClientListener>, public game::PlayerInputListener {
private:
std::unique_ptr<server::Server> m_Server;
std::unique_ptr<client::ClientConnexion> m_Connexion;
@@ -75,6 +70,8 @@ class Client : public utils::ObjectNotifier<GuiListener>, public game::PlayerInp
return m_Server.get();
}
void UpdateServerConfig();
private:
void Reset();

View File

@@ -24,7 +24,7 @@ class ClientConnexion : public network::Connexion {
virtual void HandlePacket(const protocol::ChatPacket* packet) override;
virtual void HandlePacket(const protocol::ConnexionInfoPacket* packet) override;
virtual bool Connect(const std::string& pseudo, const std::string& address, std::uint16_t port);
bool Connect(const std::string& pseudo, const std::string& address, std::uint16_t port);
game::PlayerID GetPlayerID() const {
return m_PlayerID;

View File

@@ -0,0 +1,25 @@
#pragma once
#include "blitz/common/DataBuffer.h"
#include "blitz/common/NonCopyable.h"
#include "blitz/maths/Vector.h"
#include "client/audio/AudioLoader.h"
namespace blitz {
namespace audio {
class AudioBuffer : private NonCopyable {
private:
unsigned int m_ID;
public:
AudioBuffer(AudioData&& audioData);
~AudioBuffer();
unsigned int GetID() const {
return m_ID;
}
};
} // namespace audio
} // namespace blitz

View File

@@ -0,0 +1,21 @@
#pragma once
#include "blitz/common/NonCopyable.h"
#include "blitz/maths/Vector.h"
namespace blitz {
namespace audio {
class AudioListener : private NonCopyable {
public:
AudioListener();
~AudioListener();
void SetGain(float a_Gain);
void SetPosition(const Vec3f& a_Position);
void SetVelocity(const Vec3f& a_Velocity);
void SetOrientation(const Vec3f& a_Orientation, const Vec3f& a_Up);
};
} // namespace audio
} // namespace blitz

View File

@@ -0,0 +1,24 @@
#pragma once
#include "blitz/common/DataBuffer.h"
namespace blitz {
namespace audio {
enum AudioFormat { afMono8 = 0, afMono16, afStereo8, afStereo16 };
struct AudioData {
DataBuffer m_Buffer;
AudioFormat m_Format;
std::uint32_t m_Frequency;
};
namespace AudioLoader {
// files should be 8 or 16 bits wav
AudioData LoadAudioFile(const std::string& filePath);
}; // namespace AudioLoader
} // namespace audio
} // namespace blitz

View File

@@ -0,0 +1,56 @@
#pragma once
#include "blitz/game/Listeners.h"
#include "client/audio/AudioListener.h"
#include "client/audio/AudioSource.h"
#include <map>
namespace blitz {
class Client;
namespace game {
class Player;
} // namespace game
namespace audio {
struct PlayerSound {
AudioSourcePtr m_Laser;
};
class AudioManager : public game::ClientListener, public game::GameListener {
private:
Client* m_Client;
game::Player* m_Player;
AudioListener m_Listener;
AudioSourcePtr m_MenuMusic;
AudioBufferPtr m_LaserSound;
std::map<game::PlayerID, PlayerSound> m_PlayerSources;
public:
AudioManager(Client* client);
~AudioManager();
virtual void OnGameJoin() override;
virtual void OnGameLeave() override;
virtual void OnClientPlayerJoin() override;
virtual void OnPlayerShoot(game::PlayerID player, const Vec3f& position, float yaw, float pitch) override;
virtual void OnPlayerJoin(game::PlayerID player) override;
virtual void OnPlayerLeave(game::PlayerID player) override;
void SetGlobalVolume(float volume);
void Update();
private:
void InitSounds();
AudioSourcePtr InitSourceFromFile(const std::string& fileName);
AudioSourcePtr InitSourceFromBuffer(const AudioBufferPtr& buffer);
AudioBufferPtr InitBufferFromFile(const std::string& fileName);
};
} // namespace audio
} // namespace blitz

View File

@@ -0,0 +1,43 @@
#pragma once
#include "blitz/common/NonCopyable.h"
#include "blitz/maths/Vector.h"
#include "client/audio/AudioBuffer.h"
#include <memory>
namespace blitz {
namespace audio {
typedef std::shared_ptr<AudioBuffer> AudioBufferPtr;
class AudioSource : NonCopyable {
private:
unsigned int m_ID;
AudioBufferPtr m_Buffer;
public:
enum SourceState { ssInitial = 0, ssPlaying, ssPaused, ssStopped };
AudioSource();
~AudioSource();
void SetGain(float a_Gain);
void SetPitch(float a_Pitch);
void SetPosition(const Vec3f& a_Position);
void SetDirection(const Vec3f& a_Direction);
void SetVelocity(const Vec3f& a_Velocity);
void SetLooping(bool a_Looping);
void SetRelative(bool a_Relative);
void SetBuffer(const AudioBufferPtr& a_Buffer);
SourceState GetSourceState() const;
void Play();
void Pause();
void Stop();
};
typedef std::unique_ptr<AudioSource> AudioSourcePtr;
} // namespace audio
} // namespace blitz

View File

@@ -1,10 +1,20 @@
#pragma once
/**
* \file BlitzConfig.h
* \brief File containing the blitz::BlitzConfig class
*/
#include "blitz/game/Game.h"
#include <array>
#include <string>
namespace blitz {
/**
* \enum KeyAction
* \brief Enum containing the key actions
*/
enum KeyAction {
kaAvancer = 0,
kaReculer,
@@ -16,43 +26,89 @@ enum KeyAction {
typedef std::array<int, kaMax> Keybinds;
/**
* \class BlitzConfig
* \brief Class used to manage the Blitz configuration
*/
class BlitzConfig {
private:
std::array<char, 256> m_Pseudo;
std::array<char, 20> m_Pseudo;
game::GameConfig m_ServerConfig;
bool m_VSync;
bool m_DisplayFps;
KeyAction m_CurrentAction;
Keybinds m_Keybinds{};
float m_MouseSpeed;
public:
/**
* \brief Default constructor
*/
BlitzConfig();
~BlitzConfig();
std::array<char, 256>& GetPseudo() {
std::array<char, 20>& GetPseudo() {
return m_Pseudo;
}
/**
* \brief Return whether VSync is enabled
*/
bool IsVSyncEnabled() const {
return m_VSync;
}
/**
* \brief Set whether VSync is enabled
*/
void SetVSync(bool vsync) {
m_VSync = vsync;
}
/**
* \brief Return whether the FPS display is enabled
*/
bool IsFPSDisplayEnabled() const {
return m_DisplayFps;
}
/**
* \brief Set whether the FPS display is enabled
*/
void SetFPSDisplay(bool display) {
m_DisplayFps = display;
}
/**
* \brief Get the keybinds
* \return The keybinds
*/
Keybinds& GetKeys() {
return m_Keybinds;
}
/**
* \brief Get the mouse speed
* \return The mouse speed
*/
float GetMouseSpeed() const {
return m_MouseSpeed;
}
/**
* \brief Set the mouse speed
*/
void SetMouseSpeed(float MouseSpeed) {
m_MouseSpeed = MouseSpeed;
}
/**
* \brief Get the server configuration
* \return The server configuration
*/
game::GameConfig& GetServerConfig() {
return m_ServerConfig;
}
private:
void LoadConfig();
void LoadDefaultConfig();

View File

@@ -1,5 +1,12 @@
#pragma once
/**
* \file Display.h
* \brief File containing the blitz::Display class
*/
#include "client/display/InputManager.h"
#include "client/display/PlayerController.h"
#include <memory>
#include <string>
@@ -13,7 +20,10 @@ namespace gui {
class BlitzGui;
} // namespace gui
/**
* \class Display
* \brief Class used to manage the display
*/
class Display {
private:
SDL_Window* m_Window;
@@ -28,24 +38,76 @@ class Display {
bool m_FullScreen;
Client* m_Client;
input::InputManager& m_InputManager;
std::unique_ptr<gui::BlitzGui> m_BlitzGui;
input::PlayerController m_PlayerController;
public:
Display(int width, int height, const std::string& windowName, Client* client);
/**
* \brief Constructor
* \param width The width of the window
* \param height The height of the window
* \param windowName The name of the window
* \param client The client
* \param inputManager The InputManager
*/
Display(int width, int height, const std::string& windowName, Client* client, input::InputManager& inputManager);
~Display();
/**
* \brief Return whether the display has been created
*/
bool Create();
/**
* \brief Poll the events
* \note This function should be called at the beginning of the main loop
*/
void PollEvents();
/**
* \brief Update the display
* \note Swap the buffers
*/
void Update();
/**
* \brief Render the display (ImGui)
*/
void Render();
/**
* \brief Destroy the display (Not your mother's display)
*/
void Destroy();
/**
* \brief Return whether the display should be closed
*/
bool IsCloseRequested();
/**
* \brief Return widht/height ratio
*/
float GetAspectRatio();
/**
* \brief Return the window width
*/
int GetWindowWidth();
/**
* \brief Return the window height
*/
int GetWindowHeight();
/**
* \brief Return the player controller
*/
input::PlayerController& GetPlayerController() {
return m_PlayerController;
}
private:
void InitImGui();
};

View File

@@ -1,19 +1,30 @@
#pragma once
#include "blitz/misc/ObjectNotifier.h"
#include <SDL2/SDL_events.h>
#include <functional>
namespace blitz {
namespace InputManager {
namespace input {
typedef std::function<void(int)> KeyDownCallback;
typedef std::function<void(int, int)> MouseMoveCallback;
class InputListener {
public:
virtual void OnKeyDown(int imguiKey) {}
virtual void OnMouseMove(int deltaX, int deltaY) {}
};
void BindKeyDownCallback(const KeyDownCallback&);
void BindMouseMoveCallback(const MouseMoveCallback&);
void ProcessEvent(SDL_Event& event);
void GrabMouse(bool grabInput);
bool MouseGrabbed();
class InputManager : public utils::ObjectNotifier<InputListener> {
private:
bool m_MouseInputGrabbed;
} // namespace InputManager
public:
InputManager() : m_MouseInputGrabbed(false) {}
virtual ~InputManager() {}
void ProcessEvent(SDL_Event& event) const;
void GrabMouse(bool grabInput);
bool MouseGrabbed() const;
};
} // namespace input
} // namespace blitz

View File

@@ -1,9 +1,15 @@
#pragma once
/**
* \file PlayerController.h
* \brief File containing the blitz::input::PlayerController class.
*/
#include "blitz/common/Smoothing.h"
#include "blitz/game/Listeners.h"
#include "blitz/misc/ObjectNotifier.h"
#include "blitz/misc/Time.h"
#include "client/display/InputManager.h"
namespace blitz {
@@ -17,45 +23,46 @@ class Player;
namespace input {
class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener> {
/**
* \brief Class that handles player input and sends it to the client.
* \details This class is responsible for handling player input and sending it to the server.
* It also handles the player's velocity and position.
*/
class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener>, game::ClientListener, InputListener {
private:
game::Player* m_Player;
Client* m_Client;
input::InputManager& m_InputManager;
utils::CooldownTimer<float> m_ShootTimer{1.0f};
EMASmoother m_DxSmoother;
EMASmoother m_DySmoother;
/// current (target) x-axis velocity
float m_Dx;
/// current (target) y-axis velocity
float m_Dy;
/// current z-axis velocity
float m_Dz;
// current (target) velocity
Vec3f m_Velocity;
/// maximum x-axis velocity
float m_MaxDx;
/// maximum (target) y-axis velocity
float m_MaxDy;
/// maximum z-axis velocity (velocity at initial keypress)
float m_MaxDz;
/// individual gravitational force
float m_G;
Vec3f m_MaxVelocity;
/// this is reset when the player touches the ground
bool m_OnGround;
public:
PlayerController(Client* client);
/**
* \brief Default constructor
*/
PlayerController(Client* client, input::InputManager& inputManager);
virtual ~PlayerController();
/**
* \brief Update things like player position and velocity.
*/
void Update(float delta);
void SetAttachedPlayer(game::Player* a_Player) {
m_Player = a_Player;
}
virtual void OnGameConfigUpdate() override;
virtual void OnClientPlayerJoin() override;
virtual void OnGameLeave() override;
game::Player* GetAttachedPlayer() {
return m_Player;
}
virtual void OnMouseMove(int, int) override;
private:
void MouseMotionEvent(int, int);
void UpdateShootTimer(int bpm);
void UpdatePosition(float delta);
};

View File

@@ -1,7 +1,9 @@
#pragma once
#include "blitz/game/Game.h"
#include "blitz/game/LeaderBoard.h"
#include "blitz/protocol/PacketHandler.h"
#include <vector>
namespace blitz {
@@ -12,6 +14,7 @@ namespace client {
class ClientGame : public game::Game, public protocol::PacketHandler {
private:
Client* m_Client;
game::LeaderBoard m_LeaderBoard;
public:
ClientGame(Client* client, protocol::PacketDispatcher* dispatcher);
@@ -27,6 +30,14 @@ class ClientGame : public game::Game, public protocol::PacketHandler {
virtual void HandlePacket(const protocol::UpdateHealthPacket* packet) override;
virtual void HandlePacket(const protocol::PlayerStatsPacket* packet) override;
virtual void HandlePacket(const protocol::UpdateGameStatePacket* packet) override;
virtual void HandlePacket(const protocol::ServerConfigPacket* packet) override;
virtual void AddPlayer(game::PlayerID player, const std::string& name) override;
virtual void RemovePlayer(game::PlayerID player) override;
const game::LeaderBoard& GetLeaderBoard() const {
return m_LeaderBoard;
}
private:
void RegisterHandlers();

View File

@@ -1,6 +1,7 @@
#pragma once
#include "GuiWidget.h"
#include "client/display/InputManager.h"
namespace blitz {
@@ -13,7 +14,7 @@ class BlitzGui : public GuiWidget {
enum SubMenu { Main = 0 };
public:
BlitzGui(Client* client);
BlitzGui(Client* client, input::InputManager& inputManager);
virtual void Render() override;

View File

@@ -1,6 +1,7 @@
#pragma once
#include "GuiWidget.h"
#include "client/display/InputManager.h"
namespace blitz {
@@ -9,8 +10,11 @@ class Client;
namespace gui {
class CreateGameMenu : public GuiWidget {
private:
input::InputManager& m_InputManager;
public:
CreateGameMenu(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {}
CreateGameMenu(GuiWidget* parent, Client* client, input::InputManager& inputManager);
virtual void Render() override;
};

View File

@@ -2,6 +2,7 @@
#include "GuiWidget.h"
#include "client/Client.h"
#include "client/display/InputManager.h"
#include <string>
#include <vector>
@@ -9,7 +10,7 @@ namespace blitz {
namespace gui {
class GameChatGui : public GuiWidget, GuiListener {
class GameChatGui : public GuiWidget, game::ClientListener {
private:
char InputBuf[256];
std::vector<protocol::ColoredText> m_Lines;
@@ -19,14 +20,17 @@ class GameChatGui : public GuiWidget, GuiListener {
bool ScrollToBottom = false;
bool AutoScroll = true;
float m_ChatDisplay = 0;
input::InputManager& m_InputManager;
void Draw(const char* title, bool* p_open);
void DrawMini(const char* title, bool* p_open);
public:
GameChatGui(GuiWidget* parent, Client* client);
virtual void OnTextChatReceived(const protocol::ColoredText& text);
GameChatGui(GuiWidget* parent, Client* client, input::InputManager& inputManager);
virtual ~GameChatGui();
virtual void OnTextChatReceived(const protocol::ColoredText& text) override;
virtual void Render() override;
};

View File

@@ -7,6 +7,10 @@ namespace blitz {
class Client;
namespace game {
class Player;
} // namespace game
namespace gui {
class Hud : public GuiWidget {
private:
@@ -21,7 +25,7 @@ class Hud : public GuiWidget {
private:
std::string FormatString();
void Draw(const char* title, bool* p_open);
void DrawFinishScreen();
void DrawFinishScreen(bool win);
void RenderTime(float, float);
};

View File

@@ -1,6 +1,7 @@
#pragma once
#include "GuiWidget.h"
#include "client/display/InputManager.h"
namespace blitz {
@@ -9,8 +10,11 @@ class Client;
namespace gui {
class JoinGameMenu : public GuiWidget {
private:
input::InputManager& m_InputManager;
public:
JoinGameMenu(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {}
JoinGameMenu(GuiWidget* parent, Client* client, input::InputManager& inputManager);
virtual void Render() override;
};

View File

@@ -6,14 +6,14 @@
namespace blitz {
namespace gui {
class LeaderBoard : public GuiWidget {
class LeaderBoardGui : public GuiWidget {
private:
void Draw(const char* title, bool* p_open);
utils::DelayTimer<float> m_Timer{5.0f};
public:
LeaderBoard(GuiWidget* parent, Client* client);
~LeaderBoard();
LeaderBoardGui(GuiWidget* parent, Client* client);
~LeaderBoardGui();
virtual void Render() override;
};

View File

@@ -1,19 +1,29 @@
#pragma once
#include "GuiWidget.h"
#include "blitz/game/Listeners.h"
namespace blitz {
class Client;
namespace input {
class InputManager;
} // namespace input
namespace gui {
class MainMenu : public GuiWidget {
class MainMenu : public GuiWidget, public game::ClientListener {
private:
enum SubMenu { CREATE_MENU = 0, JOIN_MENU, OPTION_MENU };
input::InputManager& m_InputManager;
public:
MainMenu(Client* client);
MainMenu(Client* client, input::InputManager& inputManager);
virtual ~MainMenu();
virtual void OnGameLeave() override;
virtual void Render() override;
};

View File

@@ -3,6 +3,7 @@
#include "GuiWidget.h"
#include "blitz/misc/Time.h"
#include "client/config/BlitzConfig.h"
#include "client/display/InputManager.h"
#include <array>
#include <string>
@@ -12,7 +13,7 @@ class Client;
namespace gui {
class OptionsMenu : public GuiWidget {
class OptionsMenu : public GuiWidget, public input::InputListener {
private:
bool m_ShowFPS;
bool m_VSync;
@@ -20,13 +21,15 @@ class OptionsMenu : public GuiWidget {
bool m_KeyPopupShouldClose;
utils::Timer m_Timer{100};
KeyAction m_CurrentAction;
input::InputManager& m_InputManager;
public:
OptionsMenu(GuiWidget* parent, Client* client);
OptionsMenu(GuiWidget* parent, Client* client, input::InputManager& inputManager);
virtual ~OptionsMenu();
virtual void Render() override;
void OnKeyEvent(int key);
virtual void OnKeyDown(int key) override;
private:
std::string GetKeyActionCodeName(KeyAction);

View File

@@ -1,13 +1,17 @@
#pragma once
#include "GuiWidget.h"
#include "client/display/InputManager.h"
namespace blitz {
namespace gui {
class ServerGui : public GuiWidget {
private:
input::InputManager& m_InputManager;
public:
ServerGui(GuiWidget* parent, Client* client);
ServerGui(GuiWidget* parent, Client* client, input::InputManager& inputManager);
virtual void Render() override;
};

View File

@@ -28,16 +28,16 @@ class BulletRenderer {
std::vector<Trail> m_Trails;
ModelLoader::Model m_BulletModel;
std::unique_ptr<shader::BulletShader> m_Shader;
unsigned int m_Vbo;
const Camera& m_Camera;
public:
BulletRenderer(const Camera& cam);
~BulletRenderer();
void AddBullet(const Vec3f& origin, float yaw, float pitch);
void AddBullet(const Vec3f& origin, float yaw, float pitch, bool firstPersson);
void Update(float delta);
void Render();
void Clear();
};
} // namespace render

View File

@@ -1,7 +1,6 @@
#pragma once
#include "blitz/game/Player.h"
#include "blitz/maths/Vector.h"
#include <cstdint>
namespace blitz {

View File

@@ -20,7 +20,7 @@ class GunShader;
namespace render {
class MainRenderer : public GuiListener, public game::PlayerInputListener {
class MainRenderer : public game::ClientListener, public game::PlayerInputListener {
private:
Client* m_Client;
ModelLoader::Model m_PlayerModel;
@@ -29,20 +29,23 @@ class MainRenderer : public GuiListener, public game::PlayerInputListener {
std::unique_ptr<shader::EntityShader> m_EntityShader;
std::unique_ptr<shader::WorldShader> m_WorldShader;
std::unique_ptr<shader::GunShader> m_GunShader;
input::PlayerController m_PlayerController;
unsigned int m_Texture;
float m_ShootTime;
Camera m_Camera;
BulletRenderer m_BulletRenderer;
input::PlayerController& m_PlayerController;
public:
MainRenderer(Client* client);
MainRenderer(Client* client, input::PlayerController& playerController);
~MainRenderer();
virtual void OnSpectatorChange(game::PlayerID player) override;
virtual void OnPlayerShoot(game::PlayerID player, const Vec3f& position, float yaw, float pitch) override;
virtual void OnLocalPlayerShoot(const Vec3f& position, float yaw, float pitch) override;
virtual void OnGameConfigUpdate() override;
virtual void OnGameLeave() override;
void Update();
void Render();
void RenderEntity(const GL::VertexArray& vao, const Vec3f& position, float yaw);

View File

@@ -1,6 +1,6 @@
#pragma once
#ifndef BLITZ_GL_LOADER_GLBNIDING
#ifdef BLITZ_GL_LOADER_GLEW
#include <GL/glew.h>
#else
#include <glbinding/gl/gl.h>

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file Server.h
* \brief File containing the blitz::server::Server class
*/
#include <map>
#include <thread>
@@ -8,7 +13,15 @@
#include "server/ServerConnexion.h"
#include "server/game/ServerGame.h"
/**
* \def SERVER_TPS
* \brief The server ticks per second
*/
#define SERVER_TPS 20
/**
* \def SERVER_TICK
* \brief The server tick duration
*/
#define SERVER_TICK 1000 / SERVER_TPS
namespace blitz {
@@ -16,6 +29,10 @@ namespace server {
typedef std::map<std::uint8_t, std::unique_ptr<ServerConnexion>> ConnexionMap;
/**
* \class Server
* \brief Class used to manage the server
*/
class Server {
private:
network::TCPListener m_Listener;
@@ -27,48 +44,117 @@ class Server {
std::thread m_Thread;
bool m_ServerRunning;
game::PlayerID m_FreePlayerID;
public:
/**
* \brief Constructor
*/
Server();
virtual ~Server();
/**
* \brief Start the server
* \param port The port
* \param blocking If the server is blocking
* \return If the server has started
*/
bool Start(std::uint16_t port, bool blocking);
void Stop(); // force the server to stop
/**
* \brief Force the server to stop
*/
void Stop();
/**
* \brief Restart the server
*/
void Restart();
/**
* \brief Add a bot
*/
void AddBot();
/**
* \brief Forcefully remove a player from the game
* \param player the id of the player to remove
*/
void KickPlayer(game::PlayerID player);
/**
* \brief Remove a connexion
* \param connexionID The connexion ID
*/
void RemoveConnexion(std::uint8_t connexionID);
/**
* \brief Broadcast a packet to all connexions
* \param packet The packet
*/
void BroadcastPacket(const protocol::Packet* packet);
/**
* \brief Broadcast a chat message
* \param msg The message
*/
void BroadcastChatMessage(const std::string& msg);
/**
* \brief Get the milliseconds per tick
* \return The milliseconds per tick
*/
float GetMSPT() const {
return m_TickCounter.GetMSPT();
}
/**
* \brief Get the ticks per second
* \return The ticks per second
*/
float GetTPS() const {
return m_TickCounter.GetTPS();
}
/**
* \brief Return whether the server is running
*/
bool IsRunning() {
return m_ServerRunning;
}
/**
* \brief Get the connexions (const version)
* \return The connexions
*/
const ConnexionMap& GetConnexions() const {
return m_Connections;
}
/**
* \brief Get the connexions
* \return The connexions
*/
ConnexionMap& GetConnexions() {
return m_Connections;
}
/**
* \brief Get the game
* \return The game
*/
ServerGame& GetGame() {
return m_Game;
}
/**
* \brief Get the listening port
* \return The listening port
*/
std::uint16_t GetListeningPort();
/**
* \brief Get a new player ID
* \return The new player ID
*/
game::PlayerID GetNewPlayerID();
private:

View File

@@ -1,5 +1,10 @@
#pragma once
/**
* \file ServerConnexion.h
* \brief File containing the blitz::server::ServerConnexion class
*/
#include "blitz/network/Connexion.h"
namespace blitz {
@@ -15,13 +20,23 @@ namespace server {
class Server;
/**
* \struct KeepAlive
* \brief Structure containing the keep alive informations
* \var KeepAlive::KeepAliveID The keep alive ID
* \var KeepAlive::SendTime The time when the keep alive was sent
* \var KeepAlive::RecievedResponse If the keep alive has recieved a response
*/
struct KeepAlive {
std::uint64_t keepAliveID = 0;
std::uint64_t sendTime;
bool recievedResponse = false;
std::uint64_t KeepAliveID = 0;
std::uint64_t SendTime;
bool RecievedResponse = false;
};
/**
* \class ServerConnexion
* \brief Class used to manage the server connexion
*/
class ServerConnexion : public network::Connexion {
private:
Server* m_Server;
@@ -31,11 +46,31 @@ class ServerConnexion : public network::Connexion {
std::string m_ChatColor;
public:
/**
* \brief Constructor
* \param server The server
* \param socket The socket
* \param id The ID of the connexion
*/
ServerConnexion(Server* server, network::TCPSocket& socket, std::uint8_t id);
/**
* \brief Move constructor
*/
ServerConnexion(ServerConnexion&& move);
virtual ~ServerConnexion();
void Start();
/**
* \brief Start the connexion
*/
void Init();
/**
* \brief Get the ID of the connexion
* \return The ID of the connexion
*/
std::uint8_t GetID() const {
return m_ID;
}
virtual void HandlePacket(const protocol::PlayerLoginPacket* packet) override;
virtual void HandlePacket(const protocol::KeepAlivePacket* packet) override;
@@ -44,11 +79,7 @@ class ServerConnexion : public network::Connexion {
virtual void HandlePacket(const protocol::PlayerPositionAndRotationPacket* packet) override;
virtual void HandlePacket(const protocol::PlayerShootPacket* packet) override;
std::uint8_t GetID() const {
return m_ID;
}
virtual bool UpdateSocket();
virtual bool UpdateSocket() override;
private:
void RegisterHandlers();
@@ -58,6 +89,7 @@ class ServerConnexion : public network::Connexion {
void InitPlayerChatColor();
void SendPlayers();
void SendGameState();
void SendServerConfig();
};
} // namespace server

View File

@@ -1,10 +1,22 @@
#pragma once
/**
* \file ServerGame.h
* \brief File containing the blitz::server::ServerGame class
*/
#include "blitz/game/Game.h"
namespace blitz {
namespace server {
/**
* \struct ServerDuration
* \brief Structure containing the server game durations
* \var ServerDuration::m_GameDuration The game duration
* \var ServerDuration::m_PrepDuration The preparation duration
* \var ServerDuration::m_EndDuration The end duration
*/
struct ServerDuration {
std::uint64_t m_GameDuration = 1000 * 3 * 60;
std::uint64_t m_PrepDuration = 1000 * 10;
@@ -13,6 +25,10 @@ struct ServerDuration {
class Server;
/**
* \class ServerGame
* \brief Class used to manage the server game
*/
class ServerGame : public game::Game {
private:
Server* m_Server;
@@ -20,22 +36,59 @@ class ServerGame : public game::Game {
ServerDuration m_ServerDuration;
public:
/**
* \brief Constructor
* \param server The server
*/
ServerGame(Server* server);
virtual ~ServerGame();
void CheckShoot(game::PlayerID player, Vec3f position, float yaw, float pitch);
/**
* \brief Process a player shoot
* \param player The player
* \param position The position of the player
* \param yaw The yaw
* \param pitch The pitch
*/
void ProcessShoot(game::PlayerID player, Vec3f position, float yaw, float pitch);
/**
* \brief Process a player login
* \param player The player
* \param name The name of the player
*/
void AddPlayer(game::PlayerID player, const std::string& name) override;
/**
* \brief Remove a player from the game if he disconnected
*/
void RemovePlayer(game::PlayerID player) override;
/**
* \brief Update the game
* \param delta The delta time in milliseconds
*/
void Tick(std::uint64_t delta) override;
void SetGameState(game::GameState gameState, std::uint64_t duration);
/**
* \brief Set the game state
* \param gameState The game state
* \param duration The duration in milliseconds
*/
virtual void UpdateGameState(game::GameState gameState, std::uint64_t duration) override;
/**
* \brief Get the server duration
* \return The server duration in milliseconds
*/
ServerDuration& GetServerDuration() {
return m_ServerDuration;
}
/**
* \brief Send the player positions
*/
void SendServerConfig();
private:
void SendPlayerPositions();
void DamagePlayer(game::Player& player, game::Player& shooter);
@@ -44,6 +97,7 @@ class ServerGame : public game::Game {
void StartGame(); // when at least 2 players joined
void CancelGame(); // when not enough players are left
void ResetPlayerStats();
void InitGameConfig();
};
} // namespace server

View File

@@ -1,23 +1,28 @@
#include "blitz/network/Network.h"
#include "client/Client.h"
#include "client/audio/AudioManager.h"
#include "client/display/Display.h"
#include "client/display/InputManager.h"
#include "client/render/MainRenderer.h"
int main(int argc, char** argv) {
blitz::Client client;
blitz::Display display(1920, 1080, "BlitzKrieg", &client);
blitz::input::InputManager inputManager;
blitz::Display display(1920, 1080, "BlitzKrieg", &client, inputManager);
if (!display.Create())
return EXIT_FAILURE;
blitz::render::MainRenderer renderer(&client);
blitz::render::MainRenderer renderer(&client, display.GetPlayerController());
blitz::audio::AudioManager audioManager(&client);
blitz::network::NetworkInitializer network;
while (!display.IsCloseRequested()) {
client.Update();
display.PollEvents();
renderer.Update();
audioManager.Update();
renderer.Render();
display.Render();
display.Update();

View File

@@ -85,7 +85,7 @@ bool DataBuffer::ReadFile(const std::string& fileName) {
return m_Buffer.size() > 0;
}
bool DataBuffer::WriteFile(const std::string& fileName) {
bool DataBuffer::WriteFile(const std::string& fileName) const {
try {
std::ofstream file(fileName, std::ostream::binary);
file.write(reinterpret_cast<const char*>(m_Buffer.data()), static_cast<std::streamsize>(m_Buffer.size()));

View File

@@ -29,6 +29,8 @@ void Game::AddPlayer(PlayerID player, const std::string& name) {
newPlayer.SetHP(MAX_HP);
GetPlayers().insert({player, newPlayer});
NotifyListeners(&GameListener::OnPlayerJoin, player);
}
void Game::RemovePlayer(PlayerID player) {
@@ -37,8 +39,17 @@ void Game::RemovePlayer(PlayerID player) {
if (it == GetPlayers().end())
return;
NotifyListeners(&GameListener::OnPlayerLeave, player);
GetPlayers().erase(it);
}
void Game::UpdateGameState(GameState newGameState, std::uint64_t timeRemaining) {
m_GameState = newGameState;
m_GameTimer.SetInterval(timeRemaining);
m_GameTimer.Reset();
NotifyListeners(&GameListener::OnGameStateUpdate, newGameState);
}
} // namespace game
} // namespace blitz

View File

@@ -0,0 +1,29 @@
#include "blitz/game/LeaderBoard.h"
namespace blitz {
namespace game {
void LeaderBoard::AddPlayer(Player* player) {
m_Players.push_back(player);
Update();
}
void LeaderBoard::RemovePlayer(PlayerID player) {
auto it = std::find_if(m_Players.begin(), m_Players.end(), [player](game::Player* p) { return p->GetID() == player; });
if (it != m_Players.end())
m_Players.erase(it);
}
void LeaderBoard::Update() {
std::sort(m_Players.begin(), m_Players.end(), [](Player* a, Player* b) {
std::uint16_t killsA = a->GetStats().m_Kills;
std::uint16_t killsB = b->GetStats().m_Kills;
if (killsA == killsB) {
return a->GetStats().m_Deaths < b->GetStats().m_Deaths;
}
return killsA > killsB;
});
}
} // namespace game
} // namespace blitz

View File

@@ -171,5 +171,13 @@ Mat4f Rotate(float angle, Vec3f axis) {
return mat;
}
Vec3f GetDirectionVectorFromRotation(float yaw, float pitch) {
return {
std::cos(yaw) * std::cos(pitch),
std::sin(pitch),
std::sin(yaw) * std::cos(pitch),
};
}
} // namespace maths
} // namespace blitz

View File

@@ -22,7 +22,7 @@ static DataBuffer Inflate(const std::uint8_t* source, std::size_t size, std::siz
static DataBuffer Deflate(const std::uint8_t* source, std::size_t size) {
DataBuffer result;
uLongf compressedSize;
uLongf compressedSize = size;
result.Resize(size); // Resize for the compressed data to fit into
compress(

View File

@@ -1,10 +1,17 @@
#include "blitz/network/Network.h"
#include "blitz/misc/Log.h"
#include <signal.h>
namespace blitz {
namespace network {
/* Catch Signal Handler function */
void signal_callback_handler(int signum) {
utils::LOGD("[Network] Caught a SIGPIPE !");
}
#ifdef _WIN32
NetworkInitializer::NetworkInitializer() {
WSADATA wsaData;
@@ -18,7 +25,10 @@ NetworkInitializer::~NetworkInitializer() {
WSACleanup();
}
#else
NetworkInitializer::NetworkInitializer() {}
NetworkInitializer::NetworkInitializer() {
/* Prevents the game for crashing when socket closes on the other side */
signal(SIGPIPE, signal_callback_handler);
}
NetworkInitializer::~NetworkInitializer() {}
#endif

View File

@@ -121,13 +121,15 @@ size_t TCPSocket::Send(const unsigned char* data, size_t size) {
while (sent < size) {
int cur = send(m_Handle, reinterpret_cast<const char*>(data + sent), static_cast<int>(size - sent), 0);
if (cur <= 0) {
m_Status = Status::Error;
Disconnect();
m_Status = Status::Error;
return 0;
}
sent += static_cast<std::size_t>(cur);
}
return sent;
}
@@ -149,6 +151,7 @@ std::size_t TCPSocket::Receive(DataBuffer& buffer, std::size_t amount) {
Disconnect();
buffer.Clear();
m_Status = Status::Error;
return 0;
}
buffer.Resize(static_cast<std::size_t>(recvAmount));

View File

@@ -20,6 +20,7 @@ static std::array<PacketPtr, static_cast<std::size_t>(PacketType::PACKET_COUNT)>
std::make_unique<PlayerLeavePacket>(),
std::make_unique<PlayerListPacket>(),
std::make_unique<PlayerStatsPacket>(),
std::make_unique<ServerConfigPacket>(),
std::make_unique<ServerTpsPacket>(),
std::make_unique<UpdateGameStatePacket>(),
std::make_unique<KeepAlivePacket>(),

View File

@@ -28,6 +28,7 @@ REGISTER_DISPATCH_CLASS(PlayerShootPacket);
REGISTER_DISPATCH_CLASS(UpdateHealthPacket);
REGISTER_DISPATCH_CLASS(PlayerStatsPacket);
REGISTER_DISPATCH_CLASS(UpdateGameStatePacket);
REGISTER_DISPATCH_CLASS(ServerConfigPacket);
} // namespace protocol
} // namespace blitz

View File

@@ -1,5 +1,6 @@
#include "blitz/protocol/packets/ChatPacket.h"
#include "blitz/common/VarInt.h"
#include "blitz/maths/Vector.h"
#include "blitz/misc/Log.h"
#include <map>
@@ -23,7 +24,7 @@ DataBuffer ChatPacket::Serialize(bool packetID) const {
WritePacketID(data, packetID);
data << static_cast<std::uint64_t>(m_Message.size());
data << VarInt{m_Message.size()};
for (const auto& part : m_Message) {
data << part.color << part.text;
}
@@ -31,12 +32,12 @@ DataBuffer ChatPacket::Serialize(bool packetID) const {
}
void ChatPacket::Deserialize(DataBuffer& data) {
std::uint64_t partsNumber;
VarInt partsNumber;
data >> partsNumber;
m_Message.resize(partsNumber);
m_Message.resize(partsNumber.GetValue());
for (std::size_t i = 0; i < partsNumber; ++i) {
for (std::size_t i = 0; i < partsNumber.GetValue(); ++i) {
data >> m_Message[i].color >> m_Message[i].text;
}
}

View File

@@ -0,0 +1,19 @@
#include "blitz/protocol/packets/ServerConfigPacket.h"
namespace blitz {
namespace protocol {
DataBuffer ServerConfigPacket::Serialize(bool packetID) const {
DataBuffer data;
WritePacketID(data, packetID);
data << m_GameConfig;
return data;
}
void ServerConfigPacket::Deserialize(DataBuffer& data) {
data >> m_GameConfig;
}
} // namespace protocol
} // namespace blitz

View File

@@ -13,7 +13,7 @@ DataBuffer GetAsset(const std::string& fileName) {
SDL_RWops* io = SDL_RWFromFile(fileName.c_str(), "rb");
assert(io != nullptr);
assert(io != nullptr && "Can't find the requested file !");
std::int64_t bufferSize = SDL_RWsize(io);

View File

@@ -1,5 +1,6 @@
#include "client/Client.h"
#include "blitz/misc/Log.h"
#include "blitz/protocol/packets/ChatPacket.h"
#include "blitz/protocol/packets/DisconnectPacket.h"
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
@@ -17,11 +18,13 @@ Client::Client() :
m_Game(std::make_unique<client::ClientGame>(this, m_Connexion->GetDispatcher())) {}
Client::~Client() {
protocol::DisconnectPacket packet("Client");
m_Connexion->SendPacket(&packet);
Disconnect();
}
void Client::Update() {
if (m_Connexion->GetSocketStatus() != network::TCPSocket::Status::Connected)
return;
if (m_Connexion->UpdateSocket()) {
static std::uint64_t lastTime = utils::GetTime();
@@ -29,6 +32,8 @@ void Client::Update() {
m_Game->Tick(utils::GetTime() - lastTime);
lastTime = utils::GetTime();
} else {
Disconnect();
}
}
@@ -36,6 +41,12 @@ bool Client::JoinGame(const std::string& pseudo, const std::string& address, std
return m_Connexion->Connect(pseudo, address, port);
}
void Client::UpdateServerConfig() {
m_Server->GetGame().LoadConfig(m_Config.GetServerConfig());
m_Server->GetGame().SendServerConfig();
}
bool Client::CreateGame(std::uint16_t port, const std::string& pseudo) {
if (!m_Server->Start(port, false))
return false;
@@ -45,18 +56,32 @@ bool Client::CreateGame(std::uint16_t port, const std::string& pseudo) {
return false;
}
UpdateServerConfig();
return true;
}
void Client::Disconnect() {
if (m_Connexion->GetSocketStatus() != network::TCPSocket::Status::Connected)
return;
protocol::DisconnectPacket packet("Client wants to leave !");
m_Connexion->SendPacket(&packet);
utils::LOGD("[Client] Disconnected !");
if (m_Server) {
m_Server->Stop();
}
m_Connexion->CloseConnection();
NotifyListeners(&game::ClientListener::OnGameLeave);
Reset();
}
void Client::Reset() {
utils::LOGD("[Client] Reset !");
// Reset server
m_Server.reset(nullptr);
m_Server = std::make_unique<server::Server>();
@@ -71,7 +96,7 @@ void Client::SendChatText(const std::string& text) {
}
void Client::ChatTextReceived(const protocol::ColoredText& text) {
NotifyListeners(&GuiListener::OnTextChatReceived, text);
NotifyListeners(&game::ClientListener::OnTextChatReceived, text);
}
void Client::SendPlayerPosAndLook(const Vec3f& position, float yaw, float pitch) {

View File

@@ -5,6 +5,7 @@
#include "blitz/misc/PrettyLog.h"
#include "blitz/protocol/packets/ChatPacket.h"
#include "blitz/protocol/packets/ConnexionInfoPacket.h"
#include "blitz/protocol/packets/DisconnectPacket.h"
#include "blitz/protocol/packets/KeepAlivePacket.h"
#include "blitz/protocol/packets/PlayerLoginPacket.h"
#include "client/Client.h"
@@ -52,7 +53,8 @@ void ClientConnexion::HandlePacket(const protocol::ChatPacket* packet) {
}
void ClientConnexion::HandlePacket(const protocol::DisconnectPacket* packet) {
utils::LOG("Disconnected !");
utils::LOG("[ClientConnexion] Disconnected ! Reason : " + packet->GetReason());
m_Client->NotifyListeners(&game::ClientListener::OnGameLeave);
}
void ClientConnexion::HandlePacket(const protocol::KeepAlivePacket* packet) {
@@ -62,6 +64,7 @@ void ClientConnexion::HandlePacket(const protocol::KeepAlivePacket* packet) {
void ClientConnexion::HandlePacket(const protocol::ConnexionInfoPacket* packet) {
m_PlayerID = packet->GetConnectionID();
utils::LOGD("[ClientConnexion] Logging in with pseudo " + m_PlayerName + " ...");
Login(m_PlayerName);
}

View File

@@ -0,0 +1,27 @@
#include "client/audio/AudioBuffer.h"
#include <AL/al.h>
namespace blitz {
namespace audio {
static const std::vector<unsigned int> AudioFormats = {
AL_FORMAT_MONO8,
AL_FORMAT_MONO16,
AL_FORMAT_STEREO8,
AL_FORMAT_STEREO16,
};
AudioBuffer::AudioBuffer(AudioData&& audioData) {
alGenBuffers(1, &m_ID);
alBufferData(m_ID, AudioFormats[audioData.m_Format], audioData.m_Buffer.data() + audioData.m_Buffer.GetReadOffset(),
audioData.m_Buffer.GetSize() - audioData.m_Buffer.GetReadOffset(), static_cast<ALsizei>(audioData.m_Frequency));
}
AudioBuffer::~AudioBuffer() {
alDeleteBuffers(1, &m_ID);
m_ID = 0;
}
} // namespace audio
} // namespace blitz

View File

@@ -0,0 +1,47 @@
#include "client/audio/AudioListener.h"
#include "blitz/misc/Log.h"
#include <AL/al.h>
#include <AL/alc.h>
namespace blitz {
namespace audio {
AudioListener::AudioListener() {
ALCdevice* device = alcOpenDevice(nullptr);
if (device) {
ALCcontext* context = alcCreateContext(device, nullptr);
alcMakeContextCurrent(context);
} else {
utils::LOGE("[AudioListener] Can't initialize sound !");
}
}
AudioListener::~AudioListener() {
ALCcontext* context = alcGetCurrentContext();
ALCdevice* device = alcGetContextsDevice(context);
alcMakeContextCurrent(NULL);
alcDestroyContext(context);
alcCloseDevice(device);
}
void AudioListener::SetGain(float a_Gain) {
alListenerf(AL_GAIN, a_Gain);
}
void AudioListener::SetPosition(const Vec3f& a_Position) {
alListener3f(AL_POSITION, a_Position.x, a_Position.y, a_Position.z);
}
void AudioListener::SetVelocity(const Vec3f& a_Velocity) {
alListener3f(AL_VELOCITY, a_Velocity.x, a_Velocity.y, a_Velocity.z);
}
void AudioListener::SetOrientation(const Vec3f& a_Orientation, const Vec3f& a_Up) {
Vec3f data[] = {a_Orientation, a_Up};
alListenerfv(AL_ORIENTATION, reinterpret_cast<float*>(data));
}
} // namespace audio
} // namespace blitz

View File

@@ -0,0 +1,51 @@
#include "client/audio/AudioLoader.h"
#include "blitz/misc/Log.h"
#include "client/AssetsManager.h"
namespace blitz {
namespace audio {
namespace AudioLoader {
struct WavHeader {
/* RIFF Chunk Descriptor */
uint8_t RIFF[4]; // RIFF Header Magic header
uint32_t ChunkSize; // RIFF Chunk Size
uint8_t WAVE[4]; // WAVE Header
/* "fmt" sub-chunk */
uint8_t FMT[4]; // FMT header
uint32_t Subchunk1Size; // Size of the fmt chunk
uint16_t AudioFormat; // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM
uint16_t NumOfChan; // Number of channels 1=Mono 2=Sterio
uint32_t SamplesPerSec; // Sampling Frequency in Hz
uint32_t BytesPerSec; // bytes per second
uint16_t BlockAlign; // 2=16-bit mono, 4=16-bit stereo
uint16_t BitsPerSample; // Number of bits per sample
/* "data" sub-chunk */
uint8_t Subchunk2ID[4]; // "data" string
uint32_t Subchunk2Size; // Sampled data length
};
AudioData LoadAudioFile(const std::string& filePath) {
DataBuffer fileBuffer = utils::AssetsManager::GetAsset(filePath);
WavHeader wavHeader;
fileBuffer >> wavHeader;
if (wavHeader.Subchunk2Size == 0) {
utils::LOGE("[AudioLoader] Failed to load sound " + filePath + " !");
}
fileBuffer.Resize(fileBuffer.GetReadOffset() + wavHeader.Subchunk2Size);
int audioFormat = (wavHeader.NumOfChan - 1) * 2 + (wavHeader.BitsPerSample / 8) - 1;
return {fileBuffer, AudioFormat(audioFormat), wavHeader.SamplesPerSec};
}
}; // namespace AudioLoader
} // namespace audio
} // namespace blitz

View File

@@ -0,0 +1,108 @@
#include "client/audio/AudioManager.h"
#include "blitz/maths/Maths.h"
#include "blitz/misc/Log.h"
#include "client/Client.h"
#include "client/audio/AudioBuffer.h"
#include "client/game/ClientGame.h"
namespace blitz {
namespace audio {
AudioManager::AudioManager(Client* client) : m_Client(client), m_Player(nullptr) {
m_Listener.SetGain(1.0f);
InitSounds();
m_MenuMusic->Play();
m_Client->BindListener(this);
}
void AudioManager::SetGlobalVolume(float volume) {
m_Listener.SetGain(volume);
}
void AudioManager::Update() {
if (!m_Player)
return;
m_Listener.SetPosition(m_Player->GetPosition());
m_Listener.SetOrientation(maths::GetDirectionVectorFromRotation(m_Player->GetYaw(), m_Player->GetPitch()), {0.0f, 1.0f, 0.0f});
m_Listener.SetVelocity(m_Player->GetVelocity());
}
AudioSourcePtr AudioManager::InitSourceFromFile(const std::string& fileName) {
AudioBufferPtr audioBuffer = InitBufferFromFile(fileName);
return InitSourceFromBuffer(audioBuffer);
}
AudioSourcePtr AudioManager::InitSourceFromBuffer(const AudioBufferPtr& buffer) {
AudioSourcePtr audioSource = std::make_unique<AudioSource>();
audioSource->SetBuffer(buffer);
audioSource->SetPosition({});
audioSource->SetVelocity({});
audioSource->SetPitch(1.0f);
audioSource->SetRelative(false);
return audioSource;
}
AudioBufferPtr AudioManager::InitBufferFromFile(const std::string& fileName) {
AudioData audioData = AudioLoader::LoadAudioFile(fileName);
return std::make_shared<AudioBuffer>(std::move(audioData));
}
void AudioManager::InitSounds() {
m_MenuMusic = InitSourceFromFile("sessionD.wav");
m_MenuMusic->SetLooping(true);
m_LaserSound = InitBufferFromFile("laser.wav");
}
void AudioManager::OnGameJoin() {
m_MenuMusic->Stop();
m_Client->GetGame()->BindListener(this);
}
void AudioManager::OnGameLeave() {
m_MenuMusic->Play();
m_PlayerSources.clear();
m_Player = nullptr;
m_Client->GetGame()->UnbindListener(this);
}
void AudioManager::OnClientPlayerJoin() {
m_Player = m_Client->GetGame()->GetPlayerById(m_Client->GetPlayerID());
}
void AudioManager::OnPlayerJoin(game::PlayerID player) {
m_PlayerSources.insert({player, PlayerSound{InitSourceFromBuffer(m_LaserSound)}});
}
void AudioManager::OnPlayerLeave(game::PlayerID player) {
m_PlayerSources.erase(player);
}
void AudioManager::OnPlayerShoot(game::PlayerID playerID, const Vec3f& position, float yaw, float pitch) {
auto it = m_PlayerSources.find(playerID);
if (it == m_PlayerSources.end()) {
utils::LOGD("[AudioManager] No sound found for player " + std::to_string(playerID) + " !");
return;
}
game::Player* player = m_Client->GetGame()->GetPlayerById(playerID);
assert(player);
Vec3f shootFront = maths::GetDirectionVectorFromRotation(player->GetYaw(), player->GetPitch());
PlayerSound& playerSounds = it->second;
playerSounds.m_Laser->SetPosition(player->GetPosition());
playerSounds.m_Laser->SetDirection(shootFront);
playerSounds.m_Laser->Play();
}
AudioManager::~AudioManager() {
m_Client->UnbindListener(this);
}
} // namespace audio
} // namespace blitz

View File

@@ -0,0 +1,70 @@
#include "client/audio/AudioSource.h"
#include <AL/al.h>
namespace blitz {
namespace audio {
AudioSource::AudioSource() {
alGenSources(1, &m_ID);
}
AudioSource::~AudioSource() {
alDeleteSources(1, &m_ID);
}
void AudioSource::SetGain(float a_Gain) {
alSourcef(m_ID, AL_GAIN, a_Gain);
}
void AudioSource::SetPitch(float a_Pitch) {
alSourcef(m_ID, AL_PITCH, a_Pitch);
}
void AudioSource::SetPosition(const Vec3f& a_Position) {
alSource3f(m_ID, AL_POSITION, a_Position.x, a_Position.y, a_Position.z);
}
void AudioSource::SetDirection(const Vec3f& a_Direction) {
alSource3f(m_ID, AL_DIRECTION, a_Direction.x, a_Direction.y, a_Direction.z);
}
void AudioSource::SetVelocity(const Vec3f& a_Velocity) {
alSource3f(m_ID, AL_VELOCITY, a_Velocity.x, a_Velocity.y, a_Velocity.z);
}
void AudioSource::SetLooping(bool a_Looping) {
alSourcei(m_ID, AL_LOOPING, a_Looping);
}
void AudioSource::SetRelative(bool a_Relative) {
alSourcei(m_ID, AL_SOURCE_RELATIVE, a_Relative);
}
void AudioSource::SetBuffer(const AudioBufferPtr& a_Buffer) {
alSourcei(m_ID, AL_BUFFER, a_Buffer->GetID());
m_Buffer = a_Buffer;
}
AudioSource::SourceState AudioSource::GetSourceState() const {
int state;
alGetSourcei(m_ID, AL_SOURCE_STATE, &state);
return SourceState(state - AL_INITIAL);
}
void AudioSource::Play() {
alSourcePlay(m_ID);
}
void AudioSource::Pause() {
alSourcePause(m_ID);
}
void AudioSource::Stop() {
alSourceStop(m_ID);
}
} // namespace audio
} // namespace blitz

View File

@@ -37,6 +37,9 @@ void BlitzConfig::LoadConfig() {
std::memcpy(m_Pseudo.data(), pseudo.data(), pseudo.size() + 1);
jsonInput.at("vsync").get_to<bool>(m_VSync);
jsonInput.at("fps").get_to<bool>(m_DisplayFps);
jsonInput.at("sensitivity").get_to<float>(m_MouseSpeed);
jsonInput.at("gravity").get_to<float>(m_ServerConfig.Gravity);
jsonInput.at("firingrate").get_to<int>(m_ServerConfig.FiringRate);
jsonInput.at("keys").get_to<Keybinds>(m_Keybinds);
utils::LOG("[BlitzConfig] Restored config !");
@@ -50,6 +53,9 @@ void BlitzConfig::LoadDefaultConfig() {
m_VSync = true;
const char defaultPseudo[] = "Pseudo";
std::memcpy(m_Pseudo.data(), defaultPseudo, sizeof(defaultPseudo));
m_MouseSpeed = 0.0025f;
m_ServerConfig.Gravity = 20.0f;
m_ServerConfig.FiringRate = 60;
m_Keybinds = {ImGuiKey_Z, ImGuiKey_S, ImGuiKey_D, ImGuiKey_Q, ImGuiKey_P};
}
@@ -64,6 +70,9 @@ void BlitzConfig::SaveConfig() {
{"pseudo", GetPseudo().data()},
{"vsync", IsVSyncEnabled()},
{"fps", IsFPSDisplayEnabled()},
{"sensitivity", GetMouseSpeed()},
{"gravity", GetServerConfig().Gravity},
{"firingrate", GetServerConfig().FiringRate},
{"keys", GetKeys()},
};

View File

@@ -12,7 +12,7 @@
#include "client/gui/BlitzGui.h"
#ifndef BLITZ_GL_LOADER_GLBNIDING
#ifdef BLITZ_GL_LOADER_GLEW
#include <GL/glew.h>
#else
#include <glbinding/glbinding.h>
@@ -20,7 +20,7 @@
namespace blitz {
Display::Display(int width, int height, const std::string& windowName, Client* client) :
Display::Display(int width, int height, const std::string& windowName, Client* client, input::InputManager& inputManager) :
m_WindowWidth(width),
m_WindowHeight(height),
m_AspectRatio(m_WindowHeight / static_cast<float>(m_WindowWidth)),
@@ -28,7 +28,9 @@ Display::Display(int width, int height, const std::string& windowName, Client* c
m_ShouldClose(false),
m_FullScreen(false),
m_Client(client),
m_BlitzGui(nullptr) {}
m_InputManager(inputManager),
m_BlitzGui(nullptr),
m_PlayerController(m_Client, m_InputManager) {}
Display::~Display() {
Destroy();
@@ -97,7 +99,7 @@ bool Display::Create() {
SDL_GL_MakeCurrent(m_Window, m_GL_Context);
SDL_GL_SetSwapInterval(1);
#ifndef BLITZ_GL_LOADER_GLBNIDING
#ifdef BLITZ_GL_LOADER_GLEW
GLenum error = glewInit();
if (error != GLEW_OK) {
utils::LOGE(utils::Format("[Display] Failed to initialise glew : %s", glewGetErrorString(error)));
@@ -145,7 +147,7 @@ void Display::PollEvents() {
}
}
ImGui_ImplSDL2_ProcessEvent(&event);
InputManager::ProcessEvent(event);
m_InputManager.ProcessEvent(event);
}
#ifdef __ANDROID__
@@ -156,6 +158,8 @@ void Display::PollEvents() {
}
#endif
m_PlayerController.Update(ImGui::GetIO().DeltaTime);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
@@ -164,7 +168,7 @@ void Display::PollEvents() {
void Display::Update() {
// center mouse
#ifndef __ANDROID__
if (InputManager::MouseGrabbed()) {
if (m_InputManager.MouseGrabbed()) {
SDL_WarpMouseInWindow(m_Window, GetWindowWidth() / 2, GetWindowHeight() / 2);
}
#endif
@@ -229,7 +233,7 @@ void Display::InitImGui() {
#ifndef __ANDROID__
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
#endif
m_BlitzGui = std::make_unique<gui::BlitzGui>(m_Client);
m_BlitzGui = std::make_unique<gui::BlitzGui>(m_Client, m_InputManager);
}
} // namespace blitz

View File

@@ -4,12 +4,7 @@
#include <vector>
namespace blitz {
namespace InputManager {
std::vector<KeyDownCallback> KeyCallBacks;
std::vector<MouseMoveCallback> MouseCallBacks;
bool MouseInputGrabbed = false;
namespace input {
static int ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode) {
switch (keycode) {
@@ -227,36 +222,15 @@ static int ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode) {
return ImGuiKey_None;
}
void BindKeyDownCallback(const KeyDownCallback& callback) {
KeyCallBacks.push_back(callback);
}
void BindMouseMoveCallback(const MouseMoveCallback& callback) {
MouseCallBacks.push_back(callback);
}
static void CallKeyFunctions(SDL_Keycode key) {
int imguiKey = ImGui_ImplSDL2_KeycodeToImGuiKey(key);
for (auto callback : KeyCallBacks) {
callback(imguiKey);
}
}
static void CallMouseFunctions(int xrel, int yrel) {
for (auto callback : MouseCallBacks) {
callback(xrel, yrel);
}
}
void ProcessEvent(SDL_Event& event) {
void InputManager::ProcessEvent(SDL_Event& event) const {
switch (event.type) {
case SDL_KEYDOWN: {
CallKeyFunctions(event.key.keysym.sym);
NotifyListeners(&InputListener::OnKeyDown, ImGui_ImplSDL2_KeycodeToImGuiKey(event.key.keysym.sym));
break;
}
case SDL_MOUSEMOTION: {
CallMouseFunctions(event.motion.xrel, event.motion.yrel);
NotifyListeners(&InputListener::OnMouseMove, event.motion.xrel, event.motion.yrel);
break;
}
@@ -265,16 +239,16 @@ void ProcessEvent(SDL_Event& event) {
}
}
void GrabMouse(bool grabInput) {
MouseInputGrabbed = grabInput;
void InputManager::GrabMouse(bool grabInput) {
m_MouseInputGrabbed = grabInput;
#ifndef __ANDROID__
SDL_SetRelativeMouseMode(static_cast<SDL_bool>(grabInput));
#endif
}
bool MouseGrabbed() {
return MouseInputGrabbed;
bool InputManager::MouseGrabbed() const {
return m_MouseInputGrabbed;
}
} // namespace InputManager
} // namespace input
} // namespace blitz

View File

@@ -3,9 +3,10 @@
#include "blitz/game/Player.h"
#include "blitz/maths/Maths.h"
#include "blitz/misc/Log.h"
#include "blitz/maths/Maths.h"
#include "client/Client.h"
#include "client/config/BlitzConfig.h"
#include "client/display/InputManager.h"
#include "client/game/ClientGame.h"
#include "imgui.h"
#include <algorithm>
#include <iostream>
@@ -14,36 +15,53 @@ namespace blitz {
namespace input {
static constexpr float DEFAULT_JUMP_VEL = 7.5;
static constexpr float DEFAULT_GRAVITY = 20.0;
static constexpr float DEFAULT_MAX_LR_SPEED = 10.;
static constexpr float DEFAULT_MAX_FB_SPEED = 10.;
static constexpr float DEFAULT_LR_SPEED_SMOOTHING_TIME = 1.0;
static constexpr float DEFAULT_FB_SPEED_SMOOTHING_TIME = 1.0;
PlayerController::PlayerController(Client* client) :
PlayerController::PlayerController(Client* client, input::InputManager& inputManager) :
m_Player(nullptr),
m_Client(client),
m_Dx(0.0),
m_Dy(0.0),
m_Dz(0.0),
m_MaxDx(DEFAULT_MAX_LR_SPEED),
m_MaxDy(DEFAULT_MAX_FB_SPEED),
m_MaxDz(DEFAULT_JUMP_VEL),
m_G(DEFAULT_GRAVITY),
m_InputManager(inputManager),
m_Velocity({}),
m_MaxVelocity(DEFAULT_MAX_LR_SPEED, DEFAULT_MAX_FB_SPEED, DEFAULT_JUMP_VEL),
m_OnGround(true) {
m_DxSmoother.Current = 0.0f;
m_DySmoother.Current = 0.0f;
m_DxSmoother.SetSmoothingTime(DEFAULT_LR_SPEED_SMOOTHING_TIME);
m_DySmoother.SetSmoothingTime(DEFAULT_FB_SPEED_SMOOTHING_TIME);
InputManager::BindMouseMoveCallback(
std::bind(&PlayerController::MouseMotionEvent, this, std::placeholders::_1, std::placeholders::_2));
m_InputManager.BindListener(this);
m_Client->BindListener(this);
}
void PlayerController::MouseMotionEvent(int deltaX, int deltaY) {
if (!m_Player || !InputManager::MouseGrabbed())
PlayerController::~PlayerController() {
m_InputManager.UnbindListener(this);
m_Client->UnbindListener(this);
}
void PlayerController::OnGameConfigUpdate() {
UpdateShootTimer(m_Client->GetGame()->GetGameConfig().FiringRate);
}
void PlayerController::OnClientPlayerJoin() {
m_Player = m_Client->GetGame()->GetPlayerById(m_Client->GetPlayerID());
}
void PlayerController::OnGameLeave() {
m_Player = nullptr;
}
void PlayerController::UpdateShootTimer(int bpm) {
m_ShootTimer.SetCooldown(60.0f / static_cast<float>(bpm));
m_ShootTimer.Reset();
}
void PlayerController::OnMouseMove(int deltaX, int deltaY) {
if (!m_Player || !m_InputManager.MouseGrabbed())
return;
static const float MouseSpeed = 0.0025f;
float MouseSpeed = m_Client->GetConfig()->GetMouseSpeed();
m_Player->AddYaw(deltaX * MouseSpeed);
m_Player->AddPitch(deltaY * -MouseSpeed);
@@ -54,7 +72,7 @@ void PlayerController::Update(float delta) {
if (!m_Player)
return;
if (InputManager::MouseGrabbed()) {
if (m_InputManager.MouseGrabbed()) {
Keybinds keys = m_Client->GetConfig()->GetKeys();
float lr = static_cast<float>(ImGui::IsKeyDown((ImGuiKey(keys[kaAvancer])))) -
static_cast<float>(ImGui::IsKeyDown((ImGuiKey(keys[kaReculer]))));
@@ -64,20 +82,22 @@ void PlayerController::Update(float delta) {
// scale values in such a way that clamps ||(lr, fb)|| to 1.0
float scale = 1.0f / std::max(sqrt(lr * lr + fb * fb), 1.0f);
m_Dx = lr * m_MaxDx * scale;
m_Dy = fb * m_MaxDy * scale;
m_Velocity.x = lr * m_MaxVelocity.x * scale;
m_Velocity.y = fb * m_MaxVelocity.y * scale;
if (ImGui::IsKeyDown(ImGuiKey::ImGuiKey_Space) && m_OnGround) {
m_Dz = m_MaxDz;
m_Velocity.z = m_MaxVelocity.z;
NotifyListeners(&game::PlayerInputListener::OnLocalPlayerJump);
}
bool canShoot = m_ShootTimer.Update(delta);
bool canShoot = m_ShootTimer.Update(ImGui::GetIO().DeltaTime);
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && canShoot) {
NotifyListeners(
&game::PlayerInputListener::OnLocalPlayerShoot, m_Player->GetPosition(), m_Player->GetYaw(), m_Player->GetPitch());
m_ShootTimer.ApplyCooldown();
}
} else {
m_Velocity.x = m_Velocity.y = 0.0f;
}
UpdatePosition(delta);
@@ -89,8 +109,8 @@ void PlayerController::UpdatePosition(const float delta) {
float sine = std::sin(yaw);
float cosine = std::cos(yaw);
m_DxSmoother.Tick(m_Dx, delta);
m_DySmoother.Tick(m_Dy, delta);
m_DxSmoother.Tick(m_Velocity.x, delta);
m_DySmoother.Tick(m_Velocity.y, delta);
float dx_smooth = m_DxSmoother.Current;
float dy_smooth = m_DySmoother.Current;
@@ -98,7 +118,7 @@ void PlayerController::UpdatePosition(const float delta) {
float dx = (dx_smooth * cosine + dy_smooth * sine) * delta;
float dy = (dx_smooth * sine - dy_smooth * cosine) * delta;
float dz = m_Dz * delta;
float dz = m_Velocity.z * delta;
// the floor here is y-level zero, once downwards collision lands it will be dynmicallly calculated
// assumed to be a negative number
@@ -106,9 +126,9 @@ void PlayerController::UpdatePosition(const float delta) {
if ((m_OnGround = (dz <= floor_dist))) {
dz = floor_dist;
m_Dz = 0.0f;
m_Velocity.z = 0.0f;
} else {
m_Dz -= m_G * delta;
m_Velocity.z -= m_Client->GetGame()->GetGameConfig().Gravity * 1.0f * delta;
}
m_Player->AddPosition({dx, dz, dy});

Some files were not shown because too many files have changed in this diff Show More