Compare commits
38 Commits
entity
...
920c2e20b3
| Author | SHA1 | Date | |
|---|---|---|---|
| 920c2e20b3 | |||
| 1e1880376d | |||
| de22c89975 | |||
| 7a388bcd62 | |||
| d1bb086daf | |||
| 7f5aee9e16 | |||
| 1bdf35a4e6 | |||
| 2bef8801e8 | |||
| c1ded40cc4 | |||
| 285bf880ee | |||
| 5492f52806 | |||
| 2cbe3f1219 | |||
| fe68b98ba1 | |||
| 860ec70829 | |||
| 06ff76607d | |||
| 19229bbe8a | |||
| 438bc4a968 | |||
| 9aa546881a | |||
| 4db03f2b83 | |||
| 0119d36b5c | |||
| 249d7534a4 | |||
|
|
abe89d2089 | ||
| f070b28d8b | |||
|
|
a7f734d22e | ||
| 2b0930a734 | |||
|
|
abbc4419fa | ||
| 84b6acad4c | |||
| 9f94d51fc4 | |||
| 9951256881 | |||
|
|
4a02054648 | ||
|
|
19c39312bf | ||
| 86e47601d7 | |||
| d5014b1e8a | |||
|
|
a3b6d2488f | ||
|
|
dccfa9c936 | ||
| e39fc8aa70 | |||
| d42f67724d | |||
| 71bc4dd249 |
38
.gitea/workflows/ubuntu.yaml
Normal file
38
.gitea/workflows/ubuntu.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Linux arm64
|
||||
run-name: Build And Test
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install deps
|
||||
run : |
|
||||
apt update
|
||||
apt install -y libsdl2-dev libassimp-dev libglew-dev
|
||||
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare XMake
|
||||
uses: xmake-io/github-action-setup-xmake@v1
|
||||
with:
|
||||
xmake-version: latest
|
||||
actions-cache-folder: '.xmake-cache'
|
||||
actions-cache-key: 'ubuntu'
|
||||
|
||||
- name: Packages cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.xmake
|
||||
key: 'ubuntu-packages'
|
||||
|
||||
- name: XMake config
|
||||
run: xmake f -p linux -y --root
|
||||
|
||||
- name: Build
|
||||
run: xmake --root
|
||||
|
||||
- name: Test
|
||||
run: xmake test --root
|
||||
20
.vscode/c_cpp_properties.json
vendored
20
.vscode/c_cpp_properties.json
vendored
@@ -1,11 +1,13 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Blitz",
|
||||
"cppStandard": "c++17",
|
||||
"includePath": ["include"],
|
||||
"compileCommands": ".vscode/compile_commands.json"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Blitz",
|
||||
"cppStandard": "c++17",
|
||||
"includePath": [
|
||||
"include"
|
||||
],
|
||||
"compileCommands": ".vscode/compile_commands.json"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
7
.vscode/launch.json
vendored
7
.vscode/launch.json
vendored
@@ -2,6 +2,13 @@
|
||||
// Xmake debug
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "xmake",
|
||||
"request": "launch",
|
||||
"name": "debug intersects test",
|
||||
"target": "test_intersects",
|
||||
"cwd": "",
|
||||
},
|
||||
{
|
||||
"type": "xmake",
|
||||
"request": "launch",
|
||||
|
||||
BIN
assets/crosshair.png
Normal file
BIN
assets/crosshair.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
BIN
assets/cube.glb
Normal file
BIN
assets/cube.glb
Normal file
Binary file not shown.
BIN
assets/fingergun.png
Normal file
BIN
assets/fingergun.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 218 KiB |
BIN
assets/jp.png
Normal file
BIN
assets/jp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
@@ -10,6 +10,7 @@
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -180,6 +181,10 @@ class DataBuffer {
|
||||
std::memcpy(newBuffer, data(), GetSize());
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
bool operator==(const DataBuffer& other) const{
|
||||
return m_Buffer == other.m_Buffer;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer);
|
||||
|
||||
@@ -28,8 +28,8 @@ class Game {
|
||||
return m_Players;
|
||||
}
|
||||
|
||||
void AddPlayer(PlayerID player, const std::string& name);
|
||||
void RemovePlayer(PlayerID player);
|
||||
virtual void AddPlayer(PlayerID player, const std::string& name);
|
||||
virtual void RemovePlayer(PlayerID player);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/Vector.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace game {
|
||||
|
||||
class PlayerListener {
|
||||
class PlayerInputListener {
|
||||
public:
|
||||
virtual void OnPlayerJump() {}
|
||||
virtual void OnPlayerShoot(const Vec3f& position, float yaw, float pitch) {}
|
||||
virtual void OnLocalPlayerJump() {}
|
||||
virtual void OnLocalPlayerShoot(const Vec3f& position, float yaw, float pitch) {}
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/Defines.h"
|
||||
#include "blitz/common/Vector.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace blitz {
|
||||
namespace game {
|
||||
|
||||
struct PlayerStats {
|
||||
std::uint16_t m_Deaths;
|
||||
std::uint16_t m_Kills;
|
||||
std::uint32_t m_ShootCount;
|
||||
std::uint32_t m_ShootSuccessCount;
|
||||
};
|
||||
|
||||
class Player {
|
||||
private:
|
||||
PlayerID m_ID;
|
||||
@@ -16,9 +23,12 @@ class Player {
|
||||
Vec3f m_Velocity;
|
||||
float m_Yaw;
|
||||
float m_Pitch;
|
||||
float m_HP;
|
||||
bool m_IsBot;
|
||||
PlayerStats m_Stats{};
|
||||
|
||||
public:
|
||||
Player(PlayerID id) : m_ID(id), m_Yaw(0), m_Pitch(0) {}
|
||||
Player(PlayerID id) : m_ID(id), m_Yaw(0), m_Pitch(0), m_IsBot(false) {}
|
||||
|
||||
PlayerID GetID() const {
|
||||
return m_ID;
|
||||
@@ -75,6 +85,26 @@ class Player {
|
||||
void AddPitch(float dPitch) {
|
||||
m_Pitch += dPitch;
|
||||
}
|
||||
|
||||
float GetHP() const {
|
||||
return m_HP;
|
||||
}
|
||||
|
||||
void SetHP(float hp) {
|
||||
m_HP = hp;
|
||||
}
|
||||
|
||||
bool IsBot() const {
|
||||
return m_IsBot;
|
||||
}
|
||||
|
||||
void SetBot() {
|
||||
m_IsBot = true;
|
||||
}
|
||||
|
||||
PlayerStats& GetStats() {
|
||||
return m_Stats;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/Vector.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace blitz {
|
||||
@@ -8,6 +8,22 @@ 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]
|
||||
*/
|
||||
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
|
||||
*/
|
||||
bool RangesOverlapping(T& a1, T& b1, T& a2, T& b2) {
|
||||
return RangesOverlap(a1, a2, b1, b2) >= 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Vectors //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@@ -55,6 +71,100 @@ 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
|
||||
|
||||
|
||||
template <typename T>
|
||||
T ReduceMin(const Vec3<T>& vect) {
|
||||
return std::min(std::min(vect.x, vect.y), vect.z);
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
template <>
|
||||
inline float ReduceMin<float>(const Vec3f& v) {
|
||||
return std::fminf(std::fminf(v.x, v.y), v.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the (signed) maximal coordinate of the vector
|
||||
*
|
||||
* @param v
|
||||
* @return constexpr T
|
||||
*/
|
||||
template <>
|
||||
inline float ReduceMax<float>(const Vec3f& v) {
|
||||
return std::fmaxf(std::fmaxf(v.x, v.y), v.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the (signed) minimal coordinate of the vector
|
||||
*
|
||||
* @param v
|
||||
* @return constexpr T
|
||||
*/
|
||||
template <>
|
||||
inline double ReduceMin<double>(const Vec3d& v) {
|
||||
return std::fmin(std::fmin(v.x, v.y), v.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the (signed) maximal coordinate of the vector
|
||||
*
|
||||
* @param v
|
||||
* @return constexpr T
|
||||
*/
|
||||
template <>
|
||||
inline double ReduceMax<double>(const Vec3d& v) {
|
||||
return std::fmax(std::fmax(v.x, v.y), v.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
template <typename T>
|
||||
constexpr Vec3<T> Min(const Vec3<T>& self, const Vec3<T>& other) {
|
||||
return {
|
||||
std::min(self.x, other.x),
|
||||
std::min(self.y, other.y),
|
||||
std::min(self.z, other.z),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param other
|
||||
* @return constexpr Vec3f
|
||||
*/
|
||||
template <typename T>
|
||||
constexpr Vec3<T> Max(const Vec3<T>& self, const Vec3<T>& other) {
|
||||
return {
|
||||
std::max(self.x, other.x),
|
||||
std::max(self.y, other.y),
|
||||
std::max(self.z, other.z),
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Matricies //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@@ -125,6 +235,8 @@ Mat4f Inverse(const Mat4f& mat);
|
||||
|
||||
Mat4f Translate(const Vec3f& translation);
|
||||
|
||||
Mat4f Scale(const Vec3f& axisFactor);
|
||||
|
||||
Mat4f RotateX(float angle);
|
||||
Mat4f RotateY(float angle);
|
||||
Mat4f RotateZ(float angle);
|
||||
30
include/blitz/maths/Physics.h
Normal file
30
include/blitz/maths/Physics.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/maths/Vector.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace maths {
|
||||
|
||||
struct Ray {
|
||||
Vec3f origin;
|
||||
Vec3f direction;
|
||||
};
|
||||
|
||||
struct AABB {
|
||||
Vec3f from;
|
||||
Vec3f to;
|
||||
};
|
||||
|
||||
inline AABB operator+(const AABB& aabb, const Vec3f& offset) {
|
||||
AABB result = aabb;
|
||||
result.from += offset;
|
||||
result.to += offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
float Distance(const Ray& ray, const AABB& aabb);
|
||||
|
||||
bool Intersects(const Ray& ray, const AABB& aabb);
|
||||
|
||||
} // namespace maths
|
||||
} // namespace blitz
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
namespace blitz {
|
||||
@@ -23,10 +25,6 @@ struct Vec2 {
|
||||
constexpr Vec2(T X = 0, T Y = 0) : x(X), y(Y) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct Vec3 {
|
||||
union {
|
||||
@@ -47,10 +45,6 @@ struct Vec3 {
|
||||
constexpr Vec3(T X = 0, T Y = 0, T Z = 0) : x(X), y(Y), z(Z) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct Vec4 {
|
||||
union {
|
||||
@@ -77,10 +71,6 @@ struct Vec4 {
|
||||
constexpr Vec4(T X = 0, T Y = 0, T Z = 0, T W = 0) : x(X), y(Y), z(Z), w(W) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using Vec2uc = Vec2<unsigned char>;
|
||||
using Vec2i = Vec2<int>;
|
||||
using Vec2u = Vec2<unsigned int>;
|
||||
@@ -178,7 +168,7 @@ Vec3<T>& operator+=(Vec3<T>& vect, const Vec3<T>& other) {
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec3<T> operator-(const Vec3<T>& vect, const Vec3<T>& other) {
|
||||
return vect + (-other);
|
||||
return {vect.x - other.x, vect.y - other.y, vect.z - other.z};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -197,9 +187,44 @@ constexpr Vec3<T> operator*(T mult, const Vec3<T>& vect) {
|
||||
return vect * mult;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec3<T> operator*=(const Vec3<T>& vect, T mult) {
|
||||
vect = vect * mult;
|
||||
return vect;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec3<T> operator*=(T mult, const Vec3<T>& vect) {
|
||||
vect = vect * mult;
|
||||
return vect;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec3<T> operator*(const Vec3<T>& vect, const Vec3<T>& other) {
|
||||
return {vect.x * other.x, vect.y * other.y, vect.z * other.z};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Vec3<T>& operator*=(Vec3<T>& vect, const Vec3<T>& other) {
|
||||
vect = vect * other;
|
||||
return vect;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr Vec3<T> operator/(const Vec3<T>& vect, const Vec3<T>& other) {
|
||||
return {vect.x / other.x, vect.y / other.y, vect.z / other.z};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Vec3<T>& operator/=(Vec3<T>& vect, const Vec3<T>& other) {
|
||||
vect = vect / other;
|
||||
return vect;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool operator<(const Vec3<T>& vec3, const Vec3<T>& other) {
|
||||
return vec3.x < other.x && vec3.y < other.y && vec3.z < other.z;
|
||||
}
|
||||
|
||||
// Vec4
|
||||
|
||||
@@ -245,10 +270,6 @@ constexpr Vec4<T> operator*(T mult, const Vec4<T>& vect) {
|
||||
return vect * mult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Matrix //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@@ -279,26 +300,18 @@ struct Mat4 {
|
||||
}
|
||||
|
||||
T at(std::size_t row, std::size_t column) const {
|
||||
return operator[](row* MATRIX_SIZE + column);
|
||||
return operator[](row * MATRIX_SIZE + column);
|
||||
}
|
||||
|
||||
T& at(std::size_t row, std::size_t column) {
|
||||
return operator[](row* MATRIX_SIZE + column);
|
||||
return operator[](row * MATRIX_SIZE + column);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef Mat4<float> Mat4f;
|
||||
typedef Mat4<int> Mat4i;
|
||||
typedef Mat4<double> Mat4d;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const Mat4<T>& mat, const Mat4<T>& other) {
|
||||
return mat.x0 == other.x0 && mat.y0 == other.y0 && mat.z0 == other.z0 && mat.w0 == other.w0 && mat.x1 == other.x1 &&
|
||||
@@ -306,5 +319,4 @@ bool operator==(const Mat4<T>& mat, const Mat4<T>& other) {
|
||||
mat.z2 == other.z2 && mat.w2 == other.w2 && mat.x3 == other.x3 && mat.y3 == other.y3 && mat.z3 == other.z3 &&
|
||||
mat.w3 == other.w3;
|
||||
}
|
||||
|
||||
} // namespace blitz
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/Vector.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include <string>
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -31,6 +31,7 @@ class PacketHandler {
|
||||
virtual void HandlePacket(const PlayerPositionAndRotationPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerShootPacket* packet) {}
|
||||
virtual void HandlePacket(const ServerTpsPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateHealthPacket* packet) {}
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
|
||||
@@ -8,4 +8,5 @@
|
||||
#include "packets/PlayerLoginPacket.h"
|
||||
#include "packets/PlayerPositionAndRotationPacket.h"
|
||||
#include "packets/PlayerShootPacket.h"
|
||||
#include "packets/ServerTpsPacket.h"
|
||||
#include "packets/ServerTpsPacket.h"
|
||||
#include "packets/UpdateHealthPacket.h"
|
||||
@@ -14,6 +14,7 @@ class PlayerLoginPacket;
|
||||
class PlayerPositionAndRotationPacket;
|
||||
class PlayerShootPacket;
|
||||
class ServerTpsPacket;
|
||||
class UpdateHealthPacket;
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace blitz
|
||||
|
||||
@@ -20,6 +20,7 @@ enum class PacketType : std::uint8_t {
|
||||
// client --> server
|
||||
|
||||
PlayerLogin = 0, /**< Corresponds to PlayerLoginPacket */
|
||||
UpdateHealth, /**< Corresponds to UpdateHealthPacket */
|
||||
|
||||
// client <-- server
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/Vector.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include "blitz/protocol/Protocol.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/Defines.h"
|
||||
#include "blitz/common/Vector.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include "blitz/protocol/Protocol.h"
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -15,13 +15,29 @@ class PlayerShootPacket : public Packet {
|
||||
public:
|
||||
PlayerShootPacket() {}
|
||||
PlayerShootPacket(Vec3f position, float yaw, float pitch, game::PlayerID player = 0) :
|
||||
m_Position(position), m_Yaw(yaw), m_Pitch(pitch), m_Player(player) {}
|
||||
m_Player(player), m_Position(position), m_Yaw(yaw), m_Pitch(pitch) {}
|
||||
virtual ~PlayerShootPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
const Vec3f& GetPosition() const {
|
||||
return m_Position;
|
||||
}
|
||||
|
||||
float GetYaw() const {
|
||||
return m_Yaw;
|
||||
}
|
||||
|
||||
float GetPitch() const {
|
||||
return m_Pitch;
|
||||
}
|
||||
|
||||
game::PlayerID GetPlayer() const {
|
||||
return m_Player;
|
||||
}
|
||||
|
||||
virtual PacketType GetType() const {
|
||||
return PacketType::PlayerShoot;
|
||||
}
|
||||
|
||||
31
include/blitz/protocol/packets/UpdateHealthPacket.h
Normal file
31
include/blitz/protocol/packets/UpdateHealthPacket.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/protocol/Protocol.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace protocol {
|
||||
|
||||
class UpdateHealthPacket : public Packet {
|
||||
private:
|
||||
float m_NewHealth;
|
||||
|
||||
public:
|
||||
UpdateHealthPacket() {}
|
||||
UpdateHealthPacket(float newHealth) : m_NewHealth(newHealth) {}
|
||||
virtual ~UpdateHealthPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
std::uint8_t GetNewHealth() const {
|
||||
return m_NewHealth;
|
||||
}
|
||||
|
||||
virtual PacketType GetType() const {
|
||||
return PacketType::UpdateHealth;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace blitz
|
||||
@@ -26,11 +26,12 @@ class Server;
|
||||
class GuiListener {
|
||||
public:
|
||||
virtual void OnTextChatReceived(const protocol::ColoredText& text) {}
|
||||
virtual void OnSpectatorChange(const game::PlayerID player) {}
|
||||
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::PlayerListener {
|
||||
class Client : public utils::ObjectNotifier<GuiListener>, public game::PlayerInputListener {
|
||||
private:
|
||||
std::unique_ptr<server::Server> m_Server;
|
||||
std::unique_ptr<client::ClientConnexion> m_Connexion;
|
||||
@@ -56,7 +57,7 @@ class Client : public utils::ObjectNotifier<GuiListener>, public game::PlayerLis
|
||||
|
||||
void SendPlayerPosAndLook(const Vec3f& position, float yaw, float pitch);
|
||||
|
||||
virtual void OnPlayerShoot(const Vec3f& position, float yaw, float pitch) override;
|
||||
virtual void OnLocalPlayerShoot(const Vec3f& position, float yaw, float pitch) override;
|
||||
|
||||
game::PlayerID GetPlayerID() const;
|
||||
|
||||
@@ -68,6 +69,12 @@ class Client : public utils::ObjectNotifier<GuiListener>, public game::PlayerLis
|
||||
return &m_Config;
|
||||
}
|
||||
|
||||
bool IsAdmin() const;
|
||||
|
||||
server::Server* GetServer() {
|
||||
return m_Server.get();
|
||||
}
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
|
||||
|
||||
@@ -5,11 +5,24 @@
|
||||
|
||||
namespace blitz {
|
||||
|
||||
enum KeyAction {
|
||||
kaAvancer = 0,
|
||||
kaReculer,
|
||||
kaDroite,
|
||||
kaGauche,
|
||||
kaMax,
|
||||
};
|
||||
|
||||
typedef std::array<int, kaMax> Keybinds;
|
||||
|
||||
class BlitzConfig {
|
||||
private:
|
||||
std::array<char, 256> m_Pseudo;
|
||||
bool m_VSync;
|
||||
bool m_DisplayFps;
|
||||
KeyAction m_CurrentAction;
|
||||
Keybinds m_Keybinds{};
|
||||
|
||||
|
||||
public:
|
||||
BlitzConfig();
|
||||
@@ -35,6 +48,10 @@ class BlitzConfig {
|
||||
m_DisplayFps = display;
|
||||
}
|
||||
|
||||
Keybinds& GetKeys() {
|
||||
return m_Keybinds;
|
||||
}
|
||||
|
||||
private:
|
||||
void LoadConfig();
|
||||
void LoadDefaultConfig();
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include "blitz/misc/Time.h"
|
||||
|
||||
namespace blitz {
|
||||
|
||||
class Client;
|
||||
|
||||
namespace game {
|
||||
|
||||
class Player;
|
||||
@@ -14,22 +17,23 @@ class Player;
|
||||
|
||||
namespace input {
|
||||
|
||||
class PlayerController : public utils::ObjectNotifier<game::PlayerListener> {
|
||||
class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener> {
|
||||
private:
|
||||
game::Player* m_Player;
|
||||
Client* m_Client;
|
||||
utils::CooldownTimer<float> m_ShootTimer{1.0f};
|
||||
EMASmoother m_DxSmoother;
|
||||
/// maximum x-axis velocity
|
||||
float m_MaxDx;
|
||||
EMASmoother m_DySmoother;
|
||||
/// current (target) x-axis velocity
|
||||
float m_Dx;
|
||||
EMASmoother m_DySmoother;
|
||||
/// maximum (target) y-axis velocity
|
||||
float m_MaxDy;
|
||||
/// current (target) y-axis velocity
|
||||
float m_Dy;
|
||||
/// current z-axis velocity
|
||||
float m_Dz;
|
||||
/// 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
|
||||
@@ -38,7 +42,7 @@ class PlayerController : public utils::ObjectNotifier<game::PlayerListener> {
|
||||
bool m_OnGround;
|
||||
|
||||
public:
|
||||
PlayerController();
|
||||
PlayerController(Client* client);
|
||||
|
||||
void Update(float delta);
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ class ClientGame : public game::Game, public protocol::PacketHandler {
|
||||
virtual void HandlePacket(const protocol::PlayerLeavePacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerListPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerPositionAndRotationPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerShootPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateHealthPacket* packet) override;
|
||||
|
||||
private:
|
||||
void RegisterHandlers();
|
||||
|
||||
19
include/client/gui/Crosshair.h
Normal file
19
include/client/gui/Crosshair.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
class CrossHair : public GuiWidget {
|
||||
private:
|
||||
int m_CrossHairTexture;
|
||||
|
||||
public:
|
||||
CrossHair(Client* client);
|
||||
|
||||
virtual void Render() override;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace blitz
|
||||
@@ -15,6 +15,9 @@ class GameChatGui : public GuiWidget, GuiListener {
|
||||
std::vector<protocol::ColoredText> m_Lines;
|
||||
std::vector<protocol::ColoredText> m_TempLines;
|
||||
bool m_FocusRequested = false;
|
||||
int HistoryPos; // -1: new line, 0..History.Size-1 browsing history.
|
||||
bool ScrollToBottom = false;
|
||||
bool AutoScroll = true;
|
||||
float m_ChatDisplay = 0;
|
||||
|
||||
|
||||
|
||||
25
include/client/gui/Hud.h
Normal file
25
include/client/gui/Hud.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
#include "client/Client.h"
|
||||
|
||||
namespace blitz {
|
||||
|
||||
class Client;
|
||||
|
||||
namespace gui {
|
||||
class Hud : public GuiWidget {
|
||||
private:
|
||||
/* data */
|
||||
|
||||
void Draw(const char* title, bool* p_open);
|
||||
unsigned int m_GunTexture;
|
||||
unsigned int m_JP;
|
||||
|
||||
public:
|
||||
Hud(GuiWidget* parent, Client* client);
|
||||
virtual void Render() override;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace blitz
|
||||
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
#include "blitz/misc/Time.h"
|
||||
#include "client/config/BlitzConfig.h"
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -12,6 +16,10 @@ class OptionsMenu : public GuiWidget {
|
||||
private:
|
||||
bool m_ShowFPS;
|
||||
bool m_VSync;
|
||||
bool m_IsKeyPopupOpen;
|
||||
bool m_KeyPopupShouldClose;
|
||||
utils::Timer m_Timer{100};
|
||||
KeyAction m_CurrentAction;
|
||||
|
||||
public:
|
||||
OptionsMenu(GuiWidget* parent, Client* client);
|
||||
@@ -19,6 +27,11 @@ class OptionsMenu : public GuiWidget {
|
||||
virtual void Render() override;
|
||||
|
||||
void OnKeyEvent(int key);
|
||||
|
||||
private:
|
||||
std::string GetKeyActionCodeName(KeyAction);
|
||||
void HotkeyBindingButton();
|
||||
void HotkeyBindingPopUp();
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
16
include/client/gui/ServerGui.h
Normal file
16
include/client/gui/ServerGui.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
class ServerGui : public GuiWidget {
|
||||
public:
|
||||
ServerGui(GuiWidget* parent, Client* client);
|
||||
|
||||
virtual void Render() override;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace blitz
|
||||
44
include/client/render/BulletRenderer.h
Normal file
44
include/client/render/BulletRenderer.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include "client/render/loader/ModelLoader.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace blitz {
|
||||
|
||||
namespace shader {
|
||||
class BulletShader;
|
||||
} // namespace shader
|
||||
|
||||
|
||||
namespace render {
|
||||
|
||||
class Camera;
|
||||
|
||||
struct Trail {
|
||||
Mat4f m_Transform;
|
||||
float m_Decay;
|
||||
};
|
||||
|
||||
|
||||
class BulletRenderer {
|
||||
private:
|
||||
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 Update(float delta);
|
||||
void Render();
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
} // namespace blitz
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/Vector.h"
|
||||
#include "blitz/game/Player.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace blitz {
|
||||
@@ -19,6 +19,8 @@ class Camera {
|
||||
|
||||
void Update(float delta);
|
||||
|
||||
static float GetPlayerEyeHeight();
|
||||
|
||||
void SetAttachedPlayer(game::Player* a_Player) {
|
||||
m_Player = a_Player;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "client/display/PlayerController.h"
|
||||
#include "client/render/BulletRenderer.h"
|
||||
#include "client/render/Camera.h"
|
||||
#include "client/render/loader/GLLoader.h"
|
||||
#include "client/render/loader/ModelLoader.h"
|
||||
@@ -19,7 +20,7 @@ class GunShader;
|
||||
|
||||
namespace render {
|
||||
|
||||
class MainRenderer : public GuiListener, public game::PlayerListener {
|
||||
class MainRenderer : public GuiListener, public game::PlayerInputListener {
|
||||
private:
|
||||
Client* m_Client;
|
||||
ModelLoader::Model m_PlayerModel;
|
||||
@@ -32,14 +33,15 @@ class MainRenderer : public GuiListener, public game::PlayerListener {
|
||||
unsigned int m_Texture;
|
||||
float m_ShootTime;
|
||||
Camera m_Camera;
|
||||
BulletRenderer m_BulletRenderer;
|
||||
|
||||
public:
|
||||
MainRenderer(Client* client);
|
||||
~MainRenderer();
|
||||
|
||||
virtual void OnSpectatorChange(const game::PlayerID player) override;
|
||||
|
||||
virtual void OnPlayerShoot(const Vec3f& position, float yaw, float pitch) override;
|
||||
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;
|
||||
|
||||
void Update();
|
||||
void Render();
|
||||
|
||||
8
include/client/render/OpenGL.h
Normal file
8
include/client/render/OpenGL.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef BLITZ_GL_LOADER_GLBNIDING
|
||||
#include <GL/glew.h>
|
||||
#else
|
||||
#include <glbinding/gl/gl.h>
|
||||
using namespace gl;
|
||||
#endif
|
||||
30
include/client/render/shader/BulletShader.h
Normal file
30
include/client/render/shader/BulletShader.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "ShaderProgram.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace shader {
|
||||
|
||||
class BulletShader : public ShaderProgram {
|
||||
private:
|
||||
unsigned int m_LocationProjectionMatrix = 0;
|
||||
unsigned int m_LocationViewMatrix = 0;
|
||||
unsigned int m_LocationAlpha = 0;
|
||||
unsigned int m_LocationTransform = 0;
|
||||
|
||||
protected:
|
||||
virtual void GetAllUniformLocation() override;
|
||||
|
||||
public:
|
||||
BulletShader();
|
||||
|
||||
bool LoadShader();
|
||||
|
||||
void SetProjectionMatrix(const Mat4f& proj) const;
|
||||
void SetViewMatrix(const Mat4f& view) const;
|
||||
void SetTransform(const Mat4f& trans) const;
|
||||
void SetDecay(float decay) const;
|
||||
};
|
||||
|
||||
} // namespace shader
|
||||
} // namespace blitz
|
||||
@@ -1,8 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/common/Vector.h"
|
||||
#include <glbinding/SharedBitfield.h>
|
||||
#include <glbinding/gl/enum.h>
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include "client/render/OpenGL.h"
|
||||
#include <string>
|
||||
|
||||
namespace blitz {
|
||||
@@ -37,7 +36,7 @@ class ShaderProgram {
|
||||
unsigned int m_VertexShaderID;
|
||||
unsigned int m_FragmentShaderID;
|
||||
|
||||
int LoadShader(const std::string& source, gl::GLenum type);
|
||||
int LoadShader(const std::string& source, GLenum type);
|
||||
};
|
||||
|
||||
} // namespace shader
|
||||
|
||||
@@ -36,6 +36,8 @@ class Server {
|
||||
|
||||
void Restart();
|
||||
|
||||
void AddBot();
|
||||
|
||||
void RemoveConnexion(std::uint8_t connexionID);
|
||||
|
||||
void BroadcastPacket(const protocol::Packet* packet);
|
||||
@@ -67,6 +69,8 @@ class Server {
|
||||
|
||||
std::uint16_t GetListeningPort();
|
||||
|
||||
game::PlayerID GetNewPlayerID();
|
||||
|
||||
private:
|
||||
void Accept();
|
||||
void UpdateSockets();
|
||||
|
||||
@@ -17,10 +17,17 @@ class ServerGame : public game::Game {
|
||||
ServerGame(Server* server);
|
||||
virtual ~ServerGame();
|
||||
|
||||
void CheckShoot(game::PlayerID player, Vec3f position, float yaw, float pitch);
|
||||
|
||||
void AddPlayer(game::PlayerID player, const std::string& name) override;
|
||||
void RemovePlayer(game::PlayerID player) override;
|
||||
|
||||
void Tick(std::uint64_t delta) override;
|
||||
|
||||
private:
|
||||
void SendPlayerPositions();
|
||||
void DamagePlayer(game::Player& player, game::Player& shooter);
|
||||
void UpdateHP(game::Player& player, float newHP);
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -30,7 +30,7 @@ DataBuffer& operator<<(DataBuffer& out, const VarInt& var) {
|
||||
|
||||
DataBuffer& operator>>(DataBuffer& in, VarInt& var) {
|
||||
var.m_Value = 0;
|
||||
int position = 0;
|
||||
unsigned int position = 0;
|
||||
std::uint8_t currentByte;
|
||||
|
||||
while (true) {
|
||||
|
||||
@@ -22,8 +22,11 @@ const Player* Game::GetPlayerById(PlayerID id) const {
|
||||
}
|
||||
|
||||
void Game::AddPlayer(PlayerID player, const std::string& name) {
|
||||
static float MAX_HP = 100;
|
||||
|
||||
game::Player newPlayer{player};
|
||||
newPlayer.SetName(name);
|
||||
newPlayer.SetHP(MAX_HP);
|
||||
|
||||
GetPlayers().insert({player, newPlayer});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "blitz/misc/Maths.h"
|
||||
#include "blitz/maths/Maths.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@@ -89,12 +89,24 @@ Mat4f Inverse(const Mat4f& mat) {
|
||||
Mat4f Translate(const Vec3f& translation) {
|
||||
Mat4f mat = Identity<float>();
|
||||
|
||||
Vec4f vh {translation.x, translation.y, translation.z, 1.0};
|
||||
Vec4f vh{translation.x, translation.y, translation.z, 1.0};
|
||||
|
||||
mat.at(3, 0) = Dot(Vec4f{mat.at(0, 0), mat.at(1, 0), mat.at(2, 0), mat.at(3, 0)}, vh);
|
||||
mat.at(3, 1) = Dot(Vec4f{mat.at(0, 1), mat.at(1, 1), mat.at(2, 1), mat.at(3, 1)}, vh);
|
||||
mat.at(3, 2) = Dot(Vec4f{mat.at(0, 2), mat.at(1, 2), mat.at(2, 2), mat.at(3, 2)}, vh);
|
||||
mat.at(3, 3) = Dot(Vec4f{mat.at(0, 3), mat.at(1, 3), mat.at(2, 3), mat.at(3, 3)}, vh);
|
||||
mat.at(3, 0) = vh.x;
|
||||
mat.at(3, 1) = vh.y;
|
||||
mat.at(3, 2) = vh.z;
|
||||
mat.at(3, 3) = vh.w;
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
|
||||
Mat4f Scale(const Vec3f& axisFactor) {
|
||||
Mat4f mat{};
|
||||
|
||||
mat.at(0, 0) = axisFactor.x;
|
||||
mat.at(1, 1) = axisFactor.y;
|
||||
mat.at(2, 2) = axisFactor.z;
|
||||
mat.at(3, 3) = 1.0f;
|
||||
|
||||
return mat;
|
||||
}
|
||||
68
src/blitz/maths/Physics.cpp
Executable file
68
src/blitz/maths/Physics.cpp
Executable file
@@ -0,0 +1,68 @@
|
||||
#include "blitz/maths/Physics.h"
|
||||
#include "blitz/maths/Maths.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace blitz {
|
||||
namespace maths {
|
||||
|
||||
/**
|
||||
* @brief Returns `true` if the half-line `ray` _strictly_ intersects with `aabb`,
|
||||
* and `false` if it _strictly_ doesn't intersect.
|
||||
* Note that if it only intersects with corners, edges, or sides of the box,
|
||||
* or if any coordinate in `ray` is `NAN` or `inf` or if any coordinate in
|
||||
* `aabb` is `NAN` the result is unspecified.
|
||||
* */
|
||||
float Distance(const Ray& ray, const AABB& aabb) {
|
||||
|
||||
// This function calculates smallest interval I = ] a, b [, for strictly positive a and b
|
||||
// such that for all t in I, for all l, r, o, d corresponding
|
||||
// coordinates in aabb.from, aabb.to, ray.origin, ray.direction, respectively
|
||||
//
|
||||
// min(l, r) < o + t * d < max(l, r)
|
||||
//
|
||||
// and returns true if it's non-empty i.e. a < b
|
||||
|
||||
// m = min(l, r), M = max(l, r)
|
||||
// m < o + t * d < M
|
||||
Vec3f l = Min(aabb.from, aabb.to);
|
||||
Vec3f r = Max(aabb.to, aabb.from);
|
||||
|
||||
// m - o < t * d < M - o
|
||||
l -= ray.origin;
|
||||
r -= ray.origin;
|
||||
|
||||
// (m - o) / d < t < (M - o) / d
|
||||
l /= ray.direction;
|
||||
r /= ray.direction;
|
||||
|
||||
// but if d is negative the inequality is flipped
|
||||
Vec3f u = Min(l, r);
|
||||
r = Max(l, r);
|
||||
l = u;
|
||||
|
||||
float tmin = ReduceMax(l);
|
||||
float tmax = ReduceMin(r);
|
||||
|
||||
// Since Min propagates NANs and ReduceMin doesn't, and since NAN !< <any float>
|
||||
// the inequality becomes ignored for coordinates where a NAN is involved
|
||||
// (as a result of 0.0 / 0.0). If all coordinates are NAN, this means
|
||||
// that the box is reduced to a point and the ray has direction 0,
|
||||
// in which case this returns -1
|
||||
if (tmax >= 0.0f && tmin <= tmax) {
|
||||
return std::fmaxf(tmin, 0.0f);
|
||||
}
|
||||
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
bool Intersects(const AABB& aabb1, const AABB& aabb2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Intersects(const Ray& ray, const AABB& aabb) {
|
||||
return Distance(ray, aabb) >= 0.0f;
|
||||
}
|
||||
|
||||
} // namespace maths
|
||||
} // namespace blitz
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "blitz/misc/Easing.h"
|
||||
|
||||
#include "blitz/misc/Maths.h"
|
||||
#include "blitz/maths/Maths.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace utils {
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace blitz {
|
||||
namespace network {
|
||||
|
||||
TCPSocket::TCPSocket() :
|
||||
m_Blocking(false), m_Status(Status::Disconnected), m_Port(0), m_Handle(static_cast<SocketHandle>(INVALID_SOCKET)) {}
|
||||
m_Blocking(false), m_Status(Status::Disconnected), m_Handle(static_cast<SocketHandle>(INVALID_SOCKET)), m_Port(0) {}
|
||||
|
||||
|
||||
TCPSocket::TCPSocket(TCPSocket&& other) {
|
||||
|
||||
@@ -14,6 +14,7 @@ typedef std::unique_ptr<Packet> PacketPtr;
|
||||
|
||||
static std::array<PacketPtr, static_cast<std::size_t>(PacketType::PACKET_COUNT)> Packets = {
|
||||
std::make_unique<PlayerLoginPacket>(),
|
||||
std::make_unique<UpdateHealthPacket>(),
|
||||
std::make_unique<ConnexionInfoPacket>(),
|
||||
std::make_unique<PlayerJoinPacket>(),
|
||||
std::make_unique<PlayerLeavePacket>(),
|
||||
|
||||
@@ -25,6 +25,7 @@ REGISTER_DISPATCH_CLASS(ServerTpsPacket)
|
||||
REGISTER_DISPATCH_CLASS(ChatPacket)
|
||||
REGISTER_DISPATCH_CLASS(PlayerPositionAndRotationPacket)
|
||||
REGISTER_DISPATCH_CLASS(PlayerShootPacket);
|
||||
REGISTER_DISPATCH_CLASS(UpdateHealthPacket);
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace blitz
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "blitz/protocol/packets/ChatPacket.h"
|
||||
|
||||
#include "blitz/common/Vector.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
@@ -20,7 +20,7 @@ void PlayerListPacket::Deserialize(DataBuffer& data) {
|
||||
VarInt playerCount;
|
||||
data >> playerCount;
|
||||
|
||||
for (int i = 0; i < playerCount.GetValue(); i++) {
|
||||
for (std::size_t i = 0; i < playerCount.GetValue(); i++) {
|
||||
std::uint8_t playerID;
|
||||
PlayerInfo playerInfo;
|
||||
data >> playerID >> playerInfo.name;
|
||||
|
||||
19
src/blitz/protocol/packets/UpdateHealthPacket.cpp
Normal file
19
src/blitz/protocol/packets/UpdateHealthPacket.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "blitz/protocol/packets/UpdateHealthPacket.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace protocol {
|
||||
|
||||
DataBuffer UpdateHealthPacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_NewHealth;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpdateHealthPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_NewHealth;
|
||||
}
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace blitz
|
||||
@@ -80,7 +80,7 @@ void Client::SendPlayerPosAndLook(const Vec3f& position, float yaw, float pitch)
|
||||
}
|
||||
|
||||
|
||||
void Client::OnPlayerShoot(const Vec3f& position, float yaw, float pitch) {
|
||||
void Client::OnLocalPlayerShoot(const Vec3f& position, float yaw, float pitch) {
|
||||
protocol::PlayerShootPacket packet(position, yaw, pitch);
|
||||
m_Connexion->SendPacket(&packet);
|
||||
}
|
||||
@@ -94,6 +94,10 @@ bool Client::IsConnected() {
|
||||
return m_Connexion->GetSocketStatus() == network::TCPSocket::Status::Connected;
|
||||
}
|
||||
|
||||
bool Client::IsAdmin() const {
|
||||
return m_Server->IsRunning();
|
||||
}
|
||||
|
||||
void Client::UpdatePosition(std::uint64_t delta) {
|
||||
// send position every tick (50 ms)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "client/config/BlitzConfig.h"
|
||||
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "imgui.h"
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
@@ -36,6 +37,7 @@ 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("keys").get_to<Keybinds>(m_Keybinds);
|
||||
|
||||
utils::LOG("[BlitzConfig] Restored config !");
|
||||
} catch (std::exception& e) {
|
||||
@@ -48,6 +50,7 @@ void BlitzConfig::LoadDefaultConfig() {
|
||||
m_VSync = true;
|
||||
const char defaultPseudo[] = "Pseudo";
|
||||
std::memcpy(m_Pseudo.data(), defaultPseudo, sizeof(defaultPseudo));
|
||||
m_Keybinds = {ImGuiKey_Z, ImGuiKey_S, ImGuiKey_D, ImGuiKey_Q};
|
||||
}
|
||||
|
||||
void BlitzConfig::SaveConfig() {
|
||||
@@ -61,6 +64,7 @@ void BlitzConfig::SaveConfig() {
|
||||
{"pseudo", GetPseudo().data()},
|
||||
{"vsync", IsVSyncEnabled()},
|
||||
{"fps", IsFPSDisplayEnabled()},
|
||||
{"keys", GetKeys()},
|
||||
};
|
||||
|
||||
file << jsonOutput;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#include "client/display/Display.h"
|
||||
|
||||
#include "client/display/InputManager.h"
|
||||
#include "client/render/OpenGL.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <backends/imgui_impl_opengl3.h>
|
||||
#include <backends/imgui_impl_sdl2.h>
|
||||
#include <glbinding/gl/gl.h>
|
||||
#include <glbinding/glbinding.h>
|
||||
|
||||
#include "blitz/misc/Format.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
@@ -13,17 +12,21 @@
|
||||
|
||||
#include "client/gui/BlitzGui.h"
|
||||
|
||||
using namespace gl;
|
||||
#ifndef BLITZ_GL_LOADER_GLBNIDING
|
||||
#include <GL/glew.h>
|
||||
#else
|
||||
#include <glbinding/glbinding.h>
|
||||
#endif
|
||||
|
||||
namespace blitz {
|
||||
|
||||
Display::Display(int width, int height, const std::string& windowName, Client* client) :
|
||||
m_WindowWidth(width),
|
||||
m_WindowHeight(height),
|
||||
m_AspectRatio(m_WindowHeight / static_cast<float>(m_WindowWidth)),
|
||||
m_WindowName(windowName),
|
||||
m_ShouldClose(false),
|
||||
m_FullScreen(false),
|
||||
m_AspectRatio(m_WindowHeight / static_cast<float>(m_WindowWidth)),
|
||||
m_Client(client),
|
||||
m_BlitzGui(nullptr) {}
|
||||
|
||||
@@ -94,7 +97,15 @@ bool Display::Create() {
|
||||
SDL_GL_MakeCurrent(m_Window, m_GL_Context);
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
|
||||
#ifndef BLITZ_GL_LOADER_GLBNIDING
|
||||
GLenum error = glewInit();
|
||||
if (error != GLEW_OK) {
|
||||
utils::LOGE(utils::Format("[Display] Failed to initialise glew : %s", glewGetErrorString(error)));
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
glbinding::initialize(reinterpret_cast<glbinding::ProcAddress (*)(const char*)>(SDL_GL_GetProcAddress));
|
||||
#endif
|
||||
|
||||
InitImGui();
|
||||
return true;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "client/display/PlayerController.h"
|
||||
|
||||
#include "blitz/game/Player.h"
|
||||
#include "blitz/maths/Maths.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "blitz/misc/Maths.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/display/InputManager.h"
|
||||
#include "imgui.h"
|
||||
#include <algorithm>
|
||||
@@ -18,14 +19,15 @@ 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() :
|
||||
PlayerController::PlayerController(Client* client) :
|
||||
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_Dz(0.0),
|
||||
m_G(DEFAULT_GRAVITY),
|
||||
m_OnGround(true) {
|
||||
m_DxSmoother.Current = 0.0f;
|
||||
@@ -52,8 +54,11 @@ void PlayerController::Update(float delta) {
|
||||
return;
|
||||
|
||||
if (InputManager::MouseGrabbed()) {
|
||||
float lr = static_cast<float>(ImGui::IsKeyDown(ImGuiKey_Z)) - static_cast<float>(ImGui::IsKeyDown(ImGuiKey_S));
|
||||
float fb = static_cast<float>(ImGui::IsKeyDown(ImGuiKey_Q)) - static_cast<float>(ImGui::IsKeyDown(ImGuiKey_D));
|
||||
Keybinds keys = m_Client->GetConfig()->GetKeys();
|
||||
float lr = static_cast<float>(ImGui::IsKeyDown((ImGuiKey(keys[kaAvancer])))) -
|
||||
static_cast<float>(ImGui::IsKeyDown((ImGuiKey(keys[kaReculer]))));
|
||||
float fb = static_cast<float>(ImGui::IsKeyDown((ImGuiKey(keys[kaGauche])))) -
|
||||
static_cast<float>(ImGui::IsKeyDown((ImGuiKey(keys[kaDroite]))));
|
||||
|
||||
// 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);
|
||||
@@ -63,12 +68,13 @@ void PlayerController::Update(float delta) {
|
||||
|
||||
if (ImGui::IsKeyDown(ImGuiKey::ImGuiKey_Space) && m_OnGround) {
|
||||
m_Dz = m_MaxDz;
|
||||
NotifyListeners(&game::PlayerListener::OnPlayerJump);
|
||||
NotifyListeners(&game::PlayerInputListener::OnLocalPlayerJump);
|
||||
}
|
||||
|
||||
bool canShoot = m_ShootTimer.Update(delta);
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && canShoot) {
|
||||
NotifyListeners(&game::PlayerListener::OnPlayerShoot, m_Player->GetPosition(), m_Player->GetYaw(), m_Player->GetPitch());
|
||||
NotifyListeners(
|
||||
&game::PlayerInputListener::OnLocalPlayerShoot, m_Player->GetPosition(), m_Player->GetYaw(), m_Player->GetPitch());
|
||||
m_ShootTimer.ApplyCooldown();
|
||||
}
|
||||
}
|
||||
@@ -97,7 +103,7 @@ void PlayerController::UpdatePosition(const float delta) {
|
||||
// assumed to be a negative number
|
||||
const float floor_dist = 0.0f - m_Player->GetPosition().y;
|
||||
|
||||
if (m_OnGround = dz <= floor_dist) {
|
||||
if ((m_OnGround = (dz <= floor_dist))) {
|
||||
dz = floor_dist;
|
||||
m_Dz = 0.0f;
|
||||
} else {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#include "client/game/ClientGame.h"
|
||||
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "blitz/misc/Random.h"
|
||||
#include "blitz/protocol/PacketDispatcher.h"
|
||||
#include "blitz/protocol/packets/PlayerJoinPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerLeavePacket.h"
|
||||
#include "blitz/protocol/packets/PlayerListPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerShootPacket.h"
|
||||
#include "blitz/protocol/packets/UpdateHealthPacket.h"
|
||||
#include "client/Client.h"
|
||||
|
||||
namespace blitz {
|
||||
@@ -25,6 +28,8 @@ void ClientGame::RegisterHandlers() {
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLeave, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerList, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerPositionAndRotation, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerShoot, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateHealth, this);
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::PlayerJoinPacket* packet) {
|
||||
@@ -46,6 +51,22 @@ void ClientGame::HandlePacket(const protocol::PlayerListPacket* packet) {
|
||||
}
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::UpdateHealthPacket* packet) {
|
||||
game::Player* player = m_Client->GetGame()->GetPlayerById(m_Client->GetPlayerID());
|
||||
player->SetHP(packet->GetNewHealth());
|
||||
|
||||
// we are dead
|
||||
if (player->GetHP() <= 0.0f) {
|
||||
player->SetPosition({utils::GetRandomReal(-10.0f, 10.0f), 0, utils::GetRandomReal(-10.0f, 10.0f)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::PlayerShootPacket* packet) {
|
||||
m_Client->NotifyListeners(
|
||||
&GuiListener::OnPlayerShoot, packet->GetPlayer(), packet->GetPosition(), packet->GetYaw(), packet->GetPitch());
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::PlayerPositionAndRotationPacket* packet) {
|
||||
if (packet->GetPlayer() == m_Client->GetPlayerID())
|
||||
return;
|
||||
@@ -61,7 +82,6 @@ void ClientGame::HandlePacket(const protocol::PlayerPositionAndRotationPacket* p
|
||||
}
|
||||
|
||||
void ClientGame::Tick(std::uint64_t delta) {
|
||||
float deltaTime = static_cast<float>(delta) / 1000.0f;
|
||||
for (auto& [playerId, player] : GetPlayers()) {
|
||||
player.SetPosition(player.GetPosition() + player.GetVelocity() * (static_cast<float>(delta) / 100.0f));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include "client/gui/BlitzGui.h"
|
||||
|
||||
#include "client/gui/Crosshair.h"
|
||||
#include "client/gui/GameChatGui.h"
|
||||
#include "client/gui/Hud.h"
|
||||
#include "client/gui/MainMenu.h"
|
||||
#include "client/gui/ServerGui.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace blitz {
|
||||
@@ -11,6 +14,9 @@ BlitzGui::BlitzGui(Client* client) : GuiWidget(nullptr, client) {
|
||||
Enable();
|
||||
AddWidget(std::make_unique<GameChatGui>(this, client));
|
||||
AddWidget(std::make_unique<MainMenu>(client));
|
||||
AddWidget(std::make_unique<CrossHair>(client));
|
||||
AddWidget(std::make_unique<ServerGui>(this, client));
|
||||
AddWidget(std::make_unique<Hud>(this, client));
|
||||
SetCustomTheme();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
#include "client/gui/ColorFulText.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
void RenderColorfulText(const protocol::ColoredText& parts, float alpha) {
|
||||
ImGuiContext& g = *ImGui::GetCurrentContext();
|
||||
for (auto& part : parts) {
|
||||
const bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
|
||||
if (need_backup)
|
||||
ImGui::PushTextWrapPos(0.0f);
|
||||
ImGui::TextColored({part.color.r, part.color.g, part.color.b, alpha}, "%s", part.text.c_str());
|
||||
if (need_backup)
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - ImGui::CalcTextSize(".").x);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ void CreateGameMenu::Render() {
|
||||
SetNextWindowFullScreen();
|
||||
|
||||
static int InputPort = 0;
|
||||
const static ImVec2 buttonSize = {300, 60};
|
||||
auto displaySize = ImGui::GetIO().DisplaySize;
|
||||
const static int paddingHeight = 40;
|
||||
|
||||
ImGui::Begin("CreateWindow", nullptr, GetWindowFullScreenFlags());
|
||||
{
|
||||
@@ -40,7 +43,9 @@ void CreateGameMenu::Render() {
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Button("Retour") || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
ImGui::SetCursorPosX(displaySize.x - buttonSize.x - paddingHeight);
|
||||
ImGui::SetCursorPosY(displaySize.y - buttonSize.y - paddingHeight);
|
||||
if (ImGui::Button("Retour", buttonSize) || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
Disable();
|
||||
m_Parent->Enable();
|
||||
}
|
||||
|
||||
29
src/client/gui/Crosshair.cpp
Normal file
29
src/client/gui/Crosshair.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "client/gui/Crosshair.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "client/render/loader/TextureLoader.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
CrossHair::CrossHair(Client* client) : GuiWidget(nullptr, client) {
|
||||
m_CrossHairTexture = TextureLoader::LoadGLTexture("crosshair.png");
|
||||
}
|
||||
|
||||
void CrossHair::Render() {
|
||||
if (!m_Client->IsConnected())
|
||||
return;
|
||||
|
||||
static const ImVec2 crossHairSize = {40, 40};
|
||||
|
||||
ImGui::SetNextWindowPos({0, 0});
|
||||
ImGui::Begin("CrossHair", nullptr, GetWindowFullScreenFlags() | ImGuiWindowFlags_NoInputs);
|
||||
ImGui::SetCursorPosX(ImGui::GetIO().DisplaySize.x / 2.0f - crossHairSize.x / 2.0f);
|
||||
ImGui::SetCursorPosY(ImGui::GetIO().DisplaySize.y / 2.0f - crossHairSize.y / 2.0f);
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(m_CrossHairTexture), crossHairSize);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace blitz
|
||||
@@ -21,22 +21,15 @@ GameChatGui::GameChatGui(GuiWidget* parent, Client* client) : GuiWidget(parent,
|
||||
}
|
||||
|
||||
void GameChatGui::Draw(const char* title, bool* p_open) {
|
||||
HistoryPos = -1;
|
||||
static int chat_width = 620;
|
||||
static int chat_height = 450;
|
||||
static int chatInput_width = 590;
|
||||
static int scrolling_width = chat_height - 90;
|
||||
ImGui::SetNextWindowPos(ImVec2(0, ImGui::GetIO().DisplaySize.y - chat_height));
|
||||
ImGui::SetNextWindowPos(ImVec2(0, ImGui::GetIO().DisplaySize.y - 2 * chat_height));
|
||||
ImGui::SetNextWindowSize(ImVec2(chat_width, chat_height));
|
||||
// const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
||||
ImGui::Begin(title, p_open, GetWindowFullScreenFlags());
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 0.73f));
|
||||
if (ImGui::BeginChild("ChatContent", ImVec2(0, chat_height - 90), false, ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
||||
for (const auto& line : m_Lines) {
|
||||
RenderColorfulText(line, 1);
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndChild();
|
||||
ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_EscapeClearsAll;
|
||||
|
||||
if (m_FocusRequested) {
|
||||
@@ -44,6 +37,10 @@ void GameChatGui::Draw(const char* title, bool* p_open) {
|
||||
m_FocusRequested = false;
|
||||
}
|
||||
|
||||
for (const auto& line : m_Lines) {
|
||||
RenderColorfulText(line, 1);
|
||||
}
|
||||
|
||||
const static ImVec4 chatColorInputText = {1.0f, 0.0f, 0.0f, 0.27f};
|
||||
ImGui::SetNextItemWidth(chatInput_width);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, chatColorInputText);
|
||||
@@ -51,6 +48,11 @@ void GameChatGui::Draw(const char* title, bool* p_open) {
|
||||
m_Client->SendChatText(InputBuf);
|
||||
InputBuf[0] = '\0';
|
||||
}
|
||||
|
||||
if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
ScrollToBottom = false;
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
@@ -59,14 +61,18 @@ void GameChatGui::Draw(const char* title, bool* p_open) {
|
||||
|
||||
void GameChatGui::DrawMini(const char* title, bool* p_open) {
|
||||
static int chat_width = 620;
|
||||
static int chat_height = 110;
|
||||
ImGui::SetNextWindowPos(ImVec2(0, ImGui::GetIO().DisplaySize.y - chat_height));
|
||||
static int chat_height = 225;
|
||||
ImGui::SetNextWindowPos(ImVec2(0, ImGui::GetIO().DisplaySize.y - 3.5 * chat_height));
|
||||
ImGui::SetNextWindowSize(ImVec2(chat_width, chat_height));
|
||||
ImGui::Begin(title, p_open, GetWindowFullScreenFlags() | ImGuiWindowFlags_NoNav);
|
||||
{
|
||||
for (const auto& line : m_TempLines) {
|
||||
RenderColorfulText(line, utils::EaseOutCubic(m_ChatDisplay / ChatFadeTime));
|
||||
}
|
||||
|
||||
if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
ScrollToBottom = false;
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
79
src/client/gui/Hud.cpp
Normal file
79
src/client/gui/Hud.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include "client/gui/Hud.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "client/game/ClientGame.h"
|
||||
#include "client/gui/GuiWidget.h"
|
||||
#include "client/render/loader/TextureLoader.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
Hud::Hud(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {
|
||||
m_GunTexture = TextureLoader::LoadGLTexture("fingergun.png");
|
||||
m_JP = TextureLoader::LoadGLTexture("jp.png");
|
||||
}
|
||||
|
||||
void Hud::Draw(const char* title, bool* p_open) {
|
||||
|
||||
SetNextWindowFullScreen();
|
||||
ImGui::Begin(title, nullptr, GetWindowFullScreenFlags() | ImGuiWindowFlags_NoInputs);
|
||||
|
||||
auto displaySize = ImGui::GetIO().DisplaySize;
|
||||
const static ImVec2 buttonSize = {300, 60};
|
||||
const static ImVec2 fingergunSize = {256, 134.5};
|
||||
const static ImVec2 jpSize = {256 / 2, 256 / 2};
|
||||
const static int paddingHeight = 40;
|
||||
const static ImVec2 pvBarPos = {displaySize.x / 2.2f, displaySize.y - 3 * paddingHeight};
|
||||
const static ImVec2 progressSize = {100.0f, 30.0f};
|
||||
const static ImVec2 currentWeaponPos = {
|
||||
displaySize.x - buttonSize.x - 3 * paddingHeight, displaySize.y - buttonSize.y - 1.5f * paddingHeight};
|
||||
const static ImVec2 currentWeaponPosImage = {
|
||||
displaySize.x - fingergunSize.x - paddingHeight, displaySize.y - fingergunSize.y + 1.0f / 2.5f * paddingHeight};
|
||||
ImVec2 spacing = ImGui::GetStyle().ItemInnerSpacing;
|
||||
|
||||
ImGui::SetCursorPosX(3 * paddingHeight);
|
||||
ImGui::SetCursorPosY(pvBarPos.y - 2 * paddingHeight);
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(m_JP), jpSize);
|
||||
|
||||
ImGui::SameLine(0.0f, paddingHeight);
|
||||
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
game::Player* player = m_Client->GetGame()->GetPlayerById(m_Client->GetPlayerID());
|
||||
|
||||
if (player) {
|
||||
ImGui::Text("PV : %.0f", player->GetHP());
|
||||
|
||||
ImGui::ProgressBar(static_cast<float>(player->GetHP() / 100.0f), progressSize, "");
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SetCursorPosX(currentWeaponPos.x);
|
||||
ImGui::SetCursorPosY(currentWeaponPos.y);
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
ImGui::Text("FingerGun");
|
||||
ImGui::SameLine(0.0f, spacing.x * 50);
|
||||
ImGui::Text("3 | 9");
|
||||
|
||||
ImGui::SetCursorPosX(currentWeaponPosImage.x);
|
||||
ImGui::SetCursorPosY(currentWeaponPosImage.y);
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(m_GunTexture), fingergunSize);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Hud::Render() {
|
||||
if (!m_Client->IsConnected())
|
||||
return;
|
||||
|
||||
Draw("Hud Blitz", nullptr);
|
||||
}
|
||||
} // namespace gui
|
||||
} // namespace blitz
|
||||
@@ -17,6 +17,9 @@ void JoinGameMenu::Render() {
|
||||
SetNextWindowFullScreen();
|
||||
|
||||
static int InputPort = 25565;
|
||||
const static ImVec2 buttonSize = {300, 60};
|
||||
auto displaySize = ImGui::GetIO().DisplaySize;
|
||||
const static int paddingHeight = 40;
|
||||
|
||||
ImGui::Begin("JoinWindow", nullptr, GetWindowFullScreenFlags());
|
||||
{
|
||||
@@ -44,7 +47,9 @@ void JoinGameMenu::Render() {
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Button("Retour") || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
ImGui::SetCursorPosX(displaySize.x - buttonSize.x - paddingHeight);
|
||||
ImGui::SetCursorPosY(displaySize.y - buttonSize.y - paddingHeight);
|
||||
if (ImGui::Button("Retour", buttonSize) || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
Disable();
|
||||
m_Parent->Enable();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "client/gui/OptionsMenu.h"
|
||||
|
||||
#include "blitz/misc/Format.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/display/InputManager.h"
|
||||
#include "client/gui/FPSMenu.h"
|
||||
@@ -9,7 +11,86 @@
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
OptionsMenu::OptionsMenu(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {
|
||||
static std::string ActionNames[kaMax] = {
|
||||
"Avancer",
|
||||
"Reculer",
|
||||
"Droite",
|
||||
"Gauche",
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static std::string GetActionName(KeyAction action) {
|
||||
return ActionNames[action];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static std::string GetImGuiKeyName(int key) {
|
||||
if (key == ImGuiKey_None) {
|
||||
return "?";
|
||||
}
|
||||
return ImGui::GetKeyName(static_cast<ImGuiKey>(key));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void OptionsMenu::HotkeyBindingButton() {
|
||||
for (std::size_t i = 0; i < m_Client->GetConfig()->GetKeys().size(); i++) {
|
||||
if (ImGui::Button(utils::Format("%s##%i", GetKeyActionCodeName(KeyAction(i)).c_str(), i).c_str())) {
|
||||
m_IsKeyPopupOpen = true;
|
||||
m_CurrentAction = KeyAction(i);
|
||||
ImGui::OpenPopup("Changer de touche");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", GetActionName(KeyAction(i)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void OptionsMenu::HotkeyBindingPopUp() {
|
||||
// Always center this window when appearing
|
||||
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||
|
||||
if (ImGui::BeginPopupModal("Changer de touche", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("Entrez la touche pour : ");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "%s", GetActionName(m_CurrentAction).c_str());
|
||||
ImGui::Text("Si vous voulez annulez cette action, appuyez sur Echap !");
|
||||
ImGui::Dummy({0, 40});
|
||||
ImGui::Text("La touche pour ");
|
||||
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "%s", GetActionName(m_CurrentAction).c_str());
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(" est : ");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "%s", GetKeyActionCodeName(m_CurrentAction).c_str());
|
||||
|
||||
if (m_KeyPopupShouldClose && m_Timer.Update(ImGui::GetIO().DeltaTime * 1000)) {
|
||||
m_KeyPopupShouldClose = false;
|
||||
m_IsKeyPopupOpen = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
OptionsMenu::OptionsMenu(GuiWidget* parent, Client* client) :
|
||||
GuiWidget(parent, client), m_IsKeyPopupOpen(false), m_KeyPopupShouldClose(false) {
|
||||
AddWidget(std::make_unique<FPSMenu>(this, client));
|
||||
InputManager::BindKeyDownCallback(std::bind(&OptionsMenu::OnKeyEvent, this, std::placeholders::_1));
|
||||
|
||||
@@ -20,7 +101,37 @@ OptionsMenu::OptionsMenu(GuiWidget* parent, Client* client) : GuiWidget(parent,
|
||||
SDL_GL_SetSwapInterval(m_VSync);
|
||||
}
|
||||
|
||||
void OptionsMenu::OnKeyEvent(int key) {}
|
||||
|
||||
|
||||
|
||||
|
||||
void OptionsMenu::OnKeyEvent(int key) {
|
||||
if (!m_IsKeyPopupOpen)
|
||||
return;
|
||||
|
||||
if (key == ImGuiKey_Escape) {
|
||||
m_KeyPopupShouldClose = true;
|
||||
ImGui::GetIO().ClearInputKeys(); // releases the Escape key
|
||||
return;
|
||||
}
|
||||
|
||||
m_Client->GetConfig()->GetKeys()[static_cast<std::size_t>(m_CurrentAction)] = key;
|
||||
m_KeyPopupShouldClose = true;
|
||||
|
||||
utils::LOG(std::to_string(key));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::string OptionsMenu::GetKeyActionCodeName(KeyAction act) {
|
||||
return GetImGuiKeyName(static_cast<int>(m_Client->GetConfig()->GetKeys()[act]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void OptionsMenu::Render() {
|
||||
GuiWidget::Render();
|
||||
@@ -34,6 +145,8 @@ void OptionsMenu::Render() {
|
||||
if (!IsEnabled())
|
||||
return;
|
||||
|
||||
const static ImVec2 buttonSize = {300, 60};
|
||||
auto displaySize = ImGui::GetIO().DisplaySize;
|
||||
const static int paddingHeight = 40;
|
||||
const static int startPos = 15;
|
||||
|
||||
@@ -47,31 +160,60 @@ void OptionsMenu::Render() {
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
if (ImGui::Checkbox("AFFICHER LES FPS", &m_ShowFPS)) {
|
||||
m_SubWidgets[0]->SetState(m_ShowFPS);
|
||||
m_Client->GetConfig()->SetFPSDisplay(m_ShowFPS);
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("VSync", &m_VSync)) {
|
||||
SDL_GL_SetSwapInterval(m_VSync);
|
||||
m_Client->GetConfig()->SetVSync(m_VSync);
|
||||
}
|
||||
|
||||
if (ImGui::Button("Retour") || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
if (ImGui::Button("Retour") || (ImGui::IsKeyPressed(ImGuiKey_Escape, false) && !m_IsKeyPopupOpen)) {
|
||||
Disable();
|
||||
if (m_Client->IsConnected()) {
|
||||
InputManager::GrabMouse(true);
|
||||
ImGui::SetCursorPosX(displaySize.x - buttonSize.x - paddingHeight);
|
||||
ImGui::SetCursorPosY(displaySize.y - 2 * buttonSize.y - paddingHeight);
|
||||
} else {
|
||||
m_Parent->Enable();
|
||||
ImGui::SetCursorPosX(displaySize.x - buttonSize.x - paddingHeight);
|
||||
ImGui::SetCursorPosY(displaySize.y - buttonSize.y - paddingHeight);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Client->IsConnected()) {
|
||||
if (ImGui::Button("Quitter la partie")) {
|
||||
m_Client->Disconnect();
|
||||
ImGui::BeginGroup();
|
||||
if (ImGui::Button("Retour", buttonSize) || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
Disable();
|
||||
m_Parent->Enable();
|
||||
if (m_Client->IsConnected()) {
|
||||
InputManager::GrabMouse(true);
|
||||
} else {
|
||||
m_Parent->Enable();
|
||||
}
|
||||
}
|
||||
if (m_Client->IsConnected()) {
|
||||
if (ImGui::Button("Quitter la partie", buttonSize)) {
|
||||
m_Client->Disconnect();
|
||||
Disable();
|
||||
m_Parent->Enable();
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
|
||||
if (ImGui::BeginTabBar("OPTIONS", tab_bar_flags)) {
|
||||
if (ImGui::BeginTabItem("CONTROLES")) {
|
||||
// Always center this window when appearing
|
||||
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||
|
||||
HotkeyBindingButton();
|
||||
HotkeyBindingPopUp();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("GRAPHISMES")) {
|
||||
if (ImGui::Checkbox("AFFICHER LES FPS", &m_ShowFPS)) {
|
||||
m_SubWidgets[0]->SetState(m_ShowFPS);
|
||||
m_Client->GetConfig()->SetFPSDisplay(m_ShowFPS);
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("VSync", &m_VSync)) {
|
||||
SDL_GL_SetSwapInterval(m_VSync);
|
||||
m_Client->GetConfig()->SetVSync(m_VSync);
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("AUDIO")) {
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
32
src/client/gui/ServerGui.cpp
Normal file
32
src/client/gui/ServerGui.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "client/gui/ServerGui.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "server/Server.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
ServerGui::ServerGui(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {}
|
||||
|
||||
void ServerGui::Render() {
|
||||
if (!m_Client->IsAdmin())
|
||||
return;
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_P)) {
|
||||
ImGui::OpenPopup("Admin panel");
|
||||
}
|
||||
|
||||
static bool popup_opened = true;
|
||||
|
||||
// this is uggly but okay for now
|
||||
if (ImGui::BeginPopupModal("Admin panel", &popup_opened)) {
|
||||
if (ImGui::Button("Add Bot")) {
|
||||
m_Client->GetServer()->AddBot();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace blitz
|
||||
79
src/client/render/BulletRenderer.cpp
Normal file
79
src/client/render/BulletRenderer.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include "client/render/BulletRenderer.h"
|
||||
|
||||
#include "blitz/maths/Maths.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "blitz/misc/Test.h"
|
||||
#include "client/render/Camera.h"
|
||||
#include "client/render/OpenGL.h"
|
||||
#include "client/render/loader/GLLoader.h"
|
||||
#include "client/render/shader/BulletShader.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace render {
|
||||
|
||||
static const float BULLET_DECAY_TIME = 5.0f;
|
||||
|
||||
BulletRenderer::BulletRenderer(const Camera& camera) : m_Camera(camera) {
|
||||
m_Shader = std::make_unique<shader::BulletShader>();
|
||||
blitz_debug_assert(m_Shader->LoadShader());
|
||||
|
||||
m_BulletModel = ModelLoader::LoadModel("cube.glb");
|
||||
}
|
||||
|
||||
BulletRenderer::~BulletRenderer() {}
|
||||
|
||||
void BulletRenderer::AddBullet(const Vec3f& origin, float yaw, float pitch) {
|
||||
static const float TRAIL_LENGHT = 50;
|
||||
|
||||
Vec3f direction = {
|
||||
std::cos(yaw) * std::cos(pitch),
|
||||
std::sin(pitch),
|
||||
std::sin(yaw) * std::cos(pitch),
|
||||
};
|
||||
|
||||
Vec3f middle = origin + direction * (TRAIL_LENGHT / 2.0f);
|
||||
|
||||
Mat4f rotate = maths::Dot(maths::RotateX(-pitch), maths::RotateY(yaw + maths::PI / 2));
|
||||
Mat4f scale = maths::Scale({0.01, 0.01, TRAIL_LENGHT / 2.0f - 0.2f});
|
||||
Mat4f translate = maths::Translate(middle);
|
||||
|
||||
Mat4f transform = maths::Dot(scale, maths::Dot(rotate, translate));
|
||||
|
||||
Trail trail{transform, BULLET_DECAY_TIME};
|
||||
m_Trails.push_back(trail);
|
||||
}
|
||||
|
||||
void BulletRenderer::Update(float delta) {
|
||||
for (Trail& trail : m_Trails) {
|
||||
trail.m_Decay -= delta;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < m_Trails.size(); i++) {
|
||||
if (m_Trails[i].m_Decay < 0) {
|
||||
m_Trails.erase(m_Trails.begin() + i);
|
||||
}
|
||||
}
|
||||
|
||||
m_Shader->Start();
|
||||
m_Shader->SetProjectionMatrix(m_Camera.GetPerspectiveMatrix());
|
||||
m_Shader->SetViewMatrix(m_Camera.GetViewMatrix());
|
||||
}
|
||||
|
||||
void BulletRenderer::Render() {
|
||||
m_Shader->Start();
|
||||
|
||||
// un peu frauduleux
|
||||
ModelLoader::VaoPtr& vao = m_BulletModel.mVaos[0];
|
||||
|
||||
vao->Bind();
|
||||
for (Trail& trail : m_Trails) {
|
||||
m_Shader->SetDecay(trail.m_Decay / BULLET_DECAY_TIME);
|
||||
m_Shader->SetTransform(trail.m_Transform);
|
||||
glDrawElements(GL_TRIANGLES, vao->GetVertexCount(), GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
vao->Unbind();
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
} // namespace blitz
|
||||
@@ -1,13 +1,13 @@
|
||||
#include "client/render/Camera.h"
|
||||
|
||||
#include "blitz/game/Player.h"
|
||||
#include "blitz/misc/Maths.h"
|
||||
#include "blitz/maths/Maths.h"
|
||||
#include "imgui.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace render {
|
||||
|
||||
static const float eyeHeight = 1.25f;
|
||||
static const float EyeHeight = 1.25f;
|
||||
|
||||
void Camera::Update(float delta) {
|
||||
int windowWidth = ImGui::GetIO().DisplaySize.x;
|
||||
@@ -21,6 +21,10 @@ void Camera::Update(float delta) {
|
||||
}
|
||||
}
|
||||
|
||||
float Camera::GetPlayerEyeHeight() {
|
||||
return EyeHeight;
|
||||
}
|
||||
|
||||
Mat4f Camera::GetViewMatrix() const {
|
||||
Vec3f front = {
|
||||
std::cos(m_Player->GetYaw()) * std::cos(m_Player->GetPitch()),
|
||||
@@ -28,7 +32,7 @@ Mat4f Camera::GetViewMatrix() const {
|
||||
std::sin(m_Player->GetYaw()) * std::cos(m_Player->GetPitch()),
|
||||
};
|
||||
|
||||
return maths::Look(m_Player->GetPosition() + Vec3f{0, eyeHeight, 0}, front, {0, 1, 0});
|
||||
return maths::Look(m_Player->GetPosition() + Vec3f{0, EyeHeight, 0}, front, {0, 1, 0});
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
#include "client/render/MainRenderer.h"
|
||||
|
||||
#include "blitz/maths/Maths.h"
|
||||
#include "blitz/misc/Easing.h"
|
||||
#include "blitz/misc/Format.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "blitz/misc/Maths.h"
|
||||
#include "blitz/misc/Test.h"
|
||||
#include "blitz/misc/Time.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/game/ClientGame.h"
|
||||
#include "client/render/OpenGL.h"
|
||||
#include "client/render/loader/GLLoader.h"
|
||||
#include "client/render/loader/ModelLoader.h"
|
||||
#include "client/render/loader/TextureLoader.h"
|
||||
#include "client/render/shader/BulletShader.h"
|
||||
#include "client/render/shader/EntityShader.h"
|
||||
#include "client/render/shader/GunShader.h"
|
||||
#include "client/render/shader/WorldShader.h"
|
||||
#include "imgui.h"
|
||||
#include <glbinding/gl/gl.h>
|
||||
|
||||
using namespace gl;
|
||||
|
||||
namespace blitz {
|
||||
namespace render {
|
||||
@@ -25,7 +24,8 @@ namespace render {
|
||||
static const Vec4f SkyColor = {0.6, 0.8, 1, 1};
|
||||
static const Vec4f MenuColor = {0, 0, 0, 0};
|
||||
|
||||
MainRenderer::MainRenderer(Client* client) : m_Client(client), m_ShootTime(0) {
|
||||
MainRenderer::MainRenderer(Client* client) :
|
||||
m_Client(client), m_PlayerController(m_Client), m_ShootTime(0), m_BulletRenderer(m_Camera) {
|
||||
|
||||
LoadModels();
|
||||
|
||||
@@ -49,6 +49,9 @@ MainRenderer::MainRenderer(Client* client) : m_Client(client), m_ShootTime(0) {
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_FRONT);
|
||||
glFrontFace(GL_CW);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
MainRenderer::~MainRenderer() {}
|
||||
@@ -89,6 +92,8 @@ void MainRenderer::Render() {
|
||||
RenderWorld();
|
||||
RenderPlayers();
|
||||
RenderGun();
|
||||
|
||||
m_BulletRenderer.Render();
|
||||
}
|
||||
|
||||
void MainRenderer::RenderPlayers() {
|
||||
@@ -101,10 +106,14 @@ void MainRenderer::RenderPlayers() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainRenderer::OnPlayerShoot(const Vec3f& position, float yaw, float pitch) {
|
||||
void MainRenderer::OnLocalPlayerShoot(const Vec3f& position, float yaw, float pitch) {
|
||||
m_ShootTime = 1.0f;
|
||||
}
|
||||
|
||||
void MainRenderer::OnPlayerShoot(game::PlayerID player, const Vec3f& position, float yaw, float pitch) {
|
||||
m_BulletRenderer.AddBullet(position + Vec3f{0.0f, Camera::GetPlayerEyeHeight(), 0.0f}, yaw, pitch);
|
||||
}
|
||||
|
||||
void MainRenderer::RenderGun() {
|
||||
if (!m_Camera.GetAttachedPlayer())
|
||||
return;
|
||||
@@ -145,17 +154,21 @@ void MainRenderer::Update() {
|
||||
|
||||
m_PlayerController.Update(delta);
|
||||
m_Camera.Update(delta);
|
||||
m_BulletRenderer.Update(delta);
|
||||
|
||||
Mat4f projectionMatrix = m_Camera.GetPerspectiveMatrix();
|
||||
Mat4f viewMatrix = m_Camera.GetViewMatrix();
|
||||
|
||||
m_EntityShader->Start();
|
||||
m_EntityShader->SetProjectionMatrix(m_Camera.GetPerspectiveMatrix());
|
||||
m_EntityShader->SetViewMatrix(m_Camera.GetViewMatrix());
|
||||
m_EntityShader->SetProjectionMatrix(projectionMatrix);
|
||||
m_EntityShader->SetViewMatrix(viewMatrix);
|
||||
|
||||
m_WorldShader->Start();
|
||||
m_WorldShader->SetProjectionMatrix(m_Camera.GetPerspectiveMatrix());
|
||||
m_WorldShader->SetViewMatrix(m_Camera.GetViewMatrix());
|
||||
m_WorldShader->SetProjectionMatrix(projectionMatrix);
|
||||
m_WorldShader->SetViewMatrix(viewMatrix);
|
||||
|
||||
m_GunShader->Start();
|
||||
m_GunShader->SetProjectionMatrix(m_Camera.GetPerspectiveMatrix());
|
||||
m_GunShader->SetProjectionMatrix(projectionMatrix);
|
||||
|
||||
m_ShootTime = std::max(0.0f, m_ShootTime - delta);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "client/render/loader/GLLoader.h"
|
||||
|
||||
#include "blitz/misc/Log.h"
|
||||
#include <glbinding/gl/gl.h>
|
||||
|
||||
using namespace gl;
|
||||
#include "client/render/OpenGL.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace GL {
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
#include "client/AssetsManager.h"
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "client/render/OpenGL.h"
|
||||
#include "stb_image.h"
|
||||
#include <glbinding/gl/gl.h>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace gl;
|
||||
|
||||
namespace blitz {
|
||||
namespace TextureLoader {
|
||||
|
||||
|
||||
67
src/client/render/shader/BulletShader.cpp
Normal file
67
src/client/render/shader/BulletShader.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "client/render/shader/BulletShader.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace shader {
|
||||
|
||||
static const std::string vertexSource = ShaderProgram::GetShaderHeader() + R"(
|
||||
|
||||
layout(location = 0) in vec3 position;
|
||||
layout(location = 1) in float decay;
|
||||
|
||||
uniform mat4 viewMatrix;
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform mat4 modelMatrix;
|
||||
|
||||
out float pass_decay;
|
||||
|
||||
void main(void){
|
||||
vec4 worldPos = modelMatrix * vec4(position, 1.0);
|
||||
pass_decay = decay;
|
||||
gl_Position = projectionMatrix * viewMatrix * worldPos;
|
||||
}
|
||||
)";
|
||||
|
||||
static const std::string fragmentSource = ShaderProgram::GetShaderHeader() + R"(
|
||||
|
||||
in float pass_decay;
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
uniform float alpha;
|
||||
|
||||
void main(void){
|
||||
out_color = vec4(1.0, 0.0, 0.0, alpha);
|
||||
}
|
||||
)";
|
||||
|
||||
BulletShader::BulletShader() : ShaderProgram() {}
|
||||
|
||||
bool BulletShader::LoadShader() {
|
||||
return ShaderProgram::LoadProgram(vertexSource, fragmentSource);
|
||||
}
|
||||
|
||||
void BulletShader::GetAllUniformLocation() {
|
||||
m_LocationViewMatrix = static_cast<unsigned int>(GetUniformLocation("viewMatrix"));
|
||||
m_LocationProjectionMatrix = static_cast<unsigned int>(GetUniformLocation("projectionMatrix"));
|
||||
m_LocationTransform = static_cast<unsigned int>(GetUniformLocation("modelMatrix"));
|
||||
m_LocationAlpha = static_cast<unsigned int>(GetUniformLocation("alpha"));
|
||||
}
|
||||
|
||||
void BulletShader::SetProjectionMatrix(const Mat4f& proj) const {
|
||||
LoadMat4(m_LocationProjectionMatrix, proj);
|
||||
}
|
||||
|
||||
void BulletShader::SetViewMatrix(const Mat4f& view) const {
|
||||
LoadMat4(m_LocationViewMatrix, view);
|
||||
}
|
||||
|
||||
void BulletShader::SetDecay(float alpha) const {
|
||||
LoadFloat(m_LocationAlpha, alpha);
|
||||
}
|
||||
|
||||
void BulletShader::SetTransform(const Mat4f& trans) const {
|
||||
LoadMat4(m_LocationTransform, trans);
|
||||
}
|
||||
|
||||
} // namespace shader
|
||||
} // namespace blitz
|
||||
@@ -44,6 +44,7 @@ void main(void){
|
||||
float brightness = diffuse;
|
||||
|
||||
out_color = vec4(1.0, 1.0, 1.0, 1.0) * brightness;
|
||||
out_color.w = 1.0;
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ out vec4 out_color;
|
||||
void main(void){
|
||||
|
||||
out_color = pos;
|
||||
out_color.w = 1.0;
|
||||
// out_color = gl_Position + vec4(0.5, 0.5, 0.5, 0);
|
||||
// out_color = texture(textureSampler, pass_textureCoords);
|
||||
|
||||
|
||||
@@ -2,14 +2,12 @@
|
||||
|
||||
#include "blitz/misc/Format.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "client/render/OpenGL.h"
|
||||
#include <fstream>
|
||||
#include <glbinding/gl/gl.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
using namespace gl;
|
||||
|
||||
namespace blitz {
|
||||
namespace shader {
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ void main(void){
|
||||
|
||||
float lightDistance = length(toLightVector);
|
||||
|
||||
const vec3 attenuation = vec3(0.3, 0.3, 0.03);
|
||||
const vec3 attenuation = vec3(0.3, 0.03, 0);
|
||||
float attenuationFactor = attenuation.x + attenuation.y * lightDistance + attenuation.z * lightDistance * lightDistance;
|
||||
|
||||
vec3 unitNormal = normalize(surfaceNormal);
|
||||
@@ -71,6 +71,7 @@ void main(void){
|
||||
float brightness = (diffuse + specular) / attenuationFactor;
|
||||
|
||||
out_color = brightness * texture(textureSampler, pass_textureCoords);
|
||||
out_color.w = 1.0;
|
||||
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "blitz/game/Game.h"
|
||||
#include "blitz/misc/Format.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "blitz/misc/Random.h"
|
||||
#include "blitz/misc/Time.h"
|
||||
#include "blitz/protocol/PacketFactory.h"
|
||||
#include "blitz/protocol/packets/ChatPacket.h"
|
||||
@@ -13,7 +14,7 @@
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
|
||||
Server::Server() : m_ServerRunning(false), m_TickCounter(SERVER_TPS), m_Game(this) {}
|
||||
Server::Server() : m_TickCounter(SERVER_TPS), m_Game(this), m_ServerRunning(false) {}
|
||||
|
||||
Server::~Server() {
|
||||
StopThread();
|
||||
@@ -100,9 +101,9 @@ void Server::Tick(std::uint64_t delta) {
|
||||
}
|
||||
|
||||
void Server::Accept() {
|
||||
static std::uint8_t newPlayerID = 0;
|
||||
network::TCPSocket newSocket;
|
||||
if (m_Listener.Accept(newSocket)) {
|
||||
game::PlayerID newPlayerID = GetNewPlayerID();
|
||||
auto con = std::make_unique<ServerConnexion>(this, newSocket, newPlayerID);
|
||||
m_Connections.insert(std::move(ConnexionMap::value_type{newPlayerID, std::move(con)}));
|
||||
m_Connections[newPlayerID]->Start();
|
||||
@@ -110,6 +111,13 @@ void Server::Accept() {
|
||||
}
|
||||
}
|
||||
|
||||
game::PlayerID Server::GetNewPlayerID() {
|
||||
static game::PlayerID lastPlayerID = 0;
|
||||
game::PlayerID newPlayerID = lastPlayerID;
|
||||
lastPlayerID++;
|
||||
return newPlayerID;
|
||||
}
|
||||
|
||||
void Server::UpdateSockets() {
|
||||
static std::vector<std::int16_t> closeConnexions;
|
||||
for (auto& connection : m_Connections) {
|
||||
@@ -154,5 +162,16 @@ std::uint16_t Server::GetListeningPort() {
|
||||
return m_Listener.GetListeningPort();
|
||||
}
|
||||
|
||||
void Server::AddBot() {
|
||||
game::PlayerID botID = GetNewPlayerID();
|
||||
|
||||
m_Game.AddPlayer(botID, "Bot " + std::to_string(static_cast<unsigned int>(botID)));
|
||||
|
||||
// set the bot at a random location to be able to see several of them
|
||||
game::Player* botPlayer = m_Game.GetPlayerById(botID);
|
||||
botPlayer->SetPosition({utils::GetRandomReal(-10.0f, 10.0f), 0.0f, utils::GetRandomReal(-10.0f, 10.0f)});
|
||||
botPlayer->SetBot();
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace blitz
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "blitz/protocol/packets/PlayerListPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerLoginPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerShootPacket.h"
|
||||
#include "client/gui/ColorFulText.h"
|
||||
#include "server/Server.h"
|
||||
#include <unordered_map>
|
||||
@@ -91,24 +92,14 @@ void ServerConnexion::InitPlayerChatColor() {
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::PlayerLoginPacket* packet) {
|
||||
game::Player newPlayer{m_ID};
|
||||
newPlayer.SetName(packet->GetPlayerName());
|
||||
|
||||
SendPlayers();
|
||||
|
||||
m_Server->GetGame().GetPlayers().insert({m_ID, newPlayer});
|
||||
m_Server->GetGame().AddPlayer(m_ID, packet->GetPlayerName());
|
||||
|
||||
m_Player = m_Server->GetGame().GetPlayerById(m_ID);
|
||||
|
||||
protocol::PlayerJoinPacket joinPacket(m_ID, m_Player->GetName());
|
||||
m_Server->BroadcastPacket(&joinPacket);
|
||||
|
||||
InitPlayerChatColor();
|
||||
|
||||
std::string joinMessage = utils::Format("%s a rejoint la partie !", packet->GetPlayerName().c_str());
|
||||
|
||||
utils::LOG("[Server] " + joinMessage);
|
||||
m_Server->BroadcastChatMessage(protocol::ChatPacket::GetTextColor(protocol::YELLOW) + joinMessage);
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::KeepAlivePacket* packet) {
|
||||
@@ -141,7 +132,10 @@ void ServerConnexion::HandlePacket(const protocol::PlayerPositionAndRotationPack
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(const protocol::PlayerShootPacket* packet) {
|
||||
utils::LOGD(utils::Format("[Server] Le joueur %s a essayé de tirer", m_Player->GetName().c_str()));
|
||||
protocol::PlayerShootPacket broadcastShoot(packet->GetPosition(), packet->GetYaw(), packet->GetPitch(), m_Player->GetID());
|
||||
m_Server->BroadcastPacket(&broadcastShoot);
|
||||
|
||||
m_Server->GetGame().CheckShoot(m_Player->GetID(), packet->GetPosition(), packet->GetYaw(), packet->GetPitch());
|
||||
}
|
||||
|
||||
void ServerConnexion::Start() {
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
#include "server/game/ServerGame.h"
|
||||
|
||||
#include "blitz/maths/Physics.h"
|
||||
#include "blitz/misc/Format.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "blitz/misc/Random.h"
|
||||
#include "blitz/protocol/packets/ChatPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerJoinPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
|
||||
#include "blitz/protocol/packets/UpdateHealthPacket.h"
|
||||
#include "server/Server.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
@@ -23,5 +31,73 @@ void ServerGame::SendPlayerPositions() {
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::CheckShoot(game::PlayerID shooter, Vec3f position, float yaw, float pitch) {
|
||||
maths::Ray shootRay;
|
||||
shootRay.origin = position + Vec3f{0.0, 1.75, 0.0};
|
||||
shootRay.direction = {
|
||||
std::cos(yaw) * std::cos(pitch),
|
||||
std::sin(pitch),
|
||||
std::sin(yaw) * std::cos(pitch),
|
||||
};
|
||||
|
||||
static const maths::AABB playerStaticAABB = {Vec3f{-0.5f, 0.0f, -0.5f}, Vec3f{0.5f, 1.8f, 0.5f}};
|
||||
|
||||
bool shootLanded = false;
|
||||
|
||||
game::Player* shooterPlayer = GetPlayerById(shooter);
|
||||
|
||||
for (auto& [playerId, player] : GetPlayers()) {
|
||||
if (playerId != shooter && maths::Intersects(shootRay, playerStaticAABB + player.GetPosition())) {
|
||||
DamagePlayer(player, *shooterPlayer);
|
||||
shootLanded = true;
|
||||
}
|
||||
}
|
||||
|
||||
shooterPlayer->GetStats().m_ShootCount++;
|
||||
if (shootLanded)
|
||||
shooterPlayer->GetStats().m_ShootSuccessCount++;
|
||||
}
|
||||
|
||||
void ServerGame::AddPlayer(game::PlayerID player, const std::string& name) {
|
||||
Game::AddPlayer(player, name);
|
||||
|
||||
protocol::PlayerJoinPacket joinPacket(player, name);
|
||||
m_Server->BroadcastPacket(&joinPacket);
|
||||
|
||||
std::string joinMessage = utils::Format("%s a rejoint la partie !", name.c_str());
|
||||
|
||||
utils::LOG("[Server] " + joinMessage);
|
||||
m_Server->BroadcastChatMessage(protocol::ChatPacket::GetTextColor(protocol::YELLOW) + joinMessage);
|
||||
}
|
||||
|
||||
void ServerGame::RemovePlayer(game::PlayerID player) {
|
||||
Game::RemovePlayer(player);
|
||||
}
|
||||
|
||||
void ServerGame::DamagePlayer(game::Player& player, game::Player& shooter) {
|
||||
static float MAX_HP = 100;
|
||||
static float GUN_DAMAGE = 50;
|
||||
|
||||
UpdateHP(player, player.GetHP() - GUN_DAMAGE);
|
||||
|
||||
// player is dead
|
||||
if (player.GetHP() <= 0.0f) {
|
||||
UpdateHP(player, MAX_HP);
|
||||
player.GetStats().m_Deaths++;
|
||||
shooter.GetStats().m_Kills++;
|
||||
player.SetPosition({utils::GetRandomReal(-10.0f, 10.0f), 0.0f, utils::GetRandomReal(-10.0f, 10.0f)});
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::UpdateHP(game::Player& player, float newHP) {
|
||||
player.SetHP(newHP);
|
||||
|
||||
if (player.IsBot())
|
||||
return;
|
||||
|
||||
protocol::UpdateHealthPacket packet(player.GetHP());
|
||||
m_Server->GetConnexions().at(player.GetID())->SendPacket(&packet);
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace blitz
|
||||
|
||||
45
test/test_compression.cpp
Normal file
45
test/test_compression.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "blitz/misc/Test.h"
|
||||
|
||||
#include "blitz/misc/Compression.h"
|
||||
|
||||
void ReciprocalTest() {
|
||||
blitz::DataBuffer original;
|
||||
original << "Some data to compress and decompress";
|
||||
|
||||
// Use your compression functions here
|
||||
blitz::DataBuffer compressed = blitz::utils::Compress(original);
|
||||
blitz::DataBuffer decompressed = blitz::utils::Decompress(compressed);
|
||||
|
||||
// Check that after compressing and then decompressing, we get back the original data
|
||||
blitz_test_assert(original == decompressed);
|
||||
}
|
||||
|
||||
void CompressionTest() {
|
||||
blitz::DataBuffer original;
|
||||
original << "Some data to compresssssssssssssssssssssssssssssssssssssssssssssssssssssssssss";
|
||||
|
||||
// Use your compression functions here
|
||||
blitz::DataBuffer compressed = blitz::utils::Compress(original);
|
||||
|
||||
// Check that the compressed data is smaller than the original
|
||||
blitz_test_assert(compressed.GetSize() < original.GetSize());
|
||||
}
|
||||
|
||||
void DecompressionTest() {
|
||||
blitz::DataBuffer original;
|
||||
original << "Some data to compress and decompress";
|
||||
|
||||
// Use your compression functions here
|
||||
blitz::DataBuffer compressed = blitz::utils::Compress(original);
|
||||
blitz::DataBuffer decompressed = blitz::utils::Decompress(compressed);
|
||||
|
||||
// Check that the decompressed data is the same size as the original
|
||||
blitz_test_assert(original.GetSize() == decompressed.GetSize());
|
||||
}
|
||||
|
||||
int main() {
|
||||
ReciprocalTest();
|
||||
CompressionTest();
|
||||
DecompressionTest();
|
||||
return BLITZ_TEST_SUCCESSFUL;
|
||||
}
|
||||
105
test/test_intersects.cpp
Executable file
105
test/test_intersects.cpp
Executable file
@@ -0,0 +1,105 @@
|
||||
#include "blitz/misc/Test.h"
|
||||
|
||||
#include "blitz/maths/Physics.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "blitz/misc/Format.h"
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <limits>
|
||||
|
||||
using namespace blitz;
|
||||
using namespace maths;
|
||||
|
||||
#define let auto // sexy boiiii
|
||||
|
||||
static void test_left() {
|
||||
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {-2.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_right() {
|
||||
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {2.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_forward() {
|
||||
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {0.0f, 2.0f, 0.0f}, {0.0f, -1.0f, 0.0f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_backward() {
|
||||
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {0.0f, -2.0f, 0.0f}, {0.0f, 1.0f, 0.0f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_above() {
|
||||
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {0.0f, 0.0f, 2.0f}, {0.0f, 0.0f, -1.0f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_below() {
|
||||
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {0.0f, 0.0f, -2.0f}, {0.0f, 0.0f, 1.0f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_shifted() {
|
||||
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {-3.0f, 0.0f, 100.0f}, {1.0f, 0.0f, 0.0f} };
|
||||
|
||||
blitz_test_assert(!Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_corner_inside() {
|
||||
let box = AABB { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {0.0f, 0.0f, 0.0f}, {0.5f, 0.5f, 0.5f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_corner_inside_weird() {
|
||||
let box = AABB { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_corner_inside_opposite_big() {
|
||||
let box = AABB { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {0.0f, 0.0f, 0.0f}, {1.5f, 1.5f, 1.5f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
static void test_corner_inside_opposite_weird() {
|
||||
let box = AABB { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
|
||||
let ray = Ray { {0.4f, 0.4f, 0.4f}, {-1.0f, -1.0f, -1.0f} };
|
||||
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
int main(int argc, const char* args[]) {
|
||||
test_left();
|
||||
test_right();
|
||||
test_forward();
|
||||
test_backward();
|
||||
test_below();
|
||||
test_above();
|
||||
test_shifted();
|
||||
test_corner_inside();
|
||||
test_corner_inside_weird();
|
||||
test_corner_inside_opposite_big();
|
||||
test_corner_inside_opposite_weird();
|
||||
return BLITZ_TEST_SUCCESSFUL;
|
||||
}
|
||||
46
test/test_network.cpp
Normal file
46
test/test_network.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "blitz/misc/Test.h"
|
||||
|
||||
#include "blitz/network/TCPListener.h"
|
||||
#include "blitz/network/TCPSocket.h"
|
||||
#include "blitz/misc/Random.h"
|
||||
|
||||
// Test the connection and disconnection of a TCPSocket
|
||||
void ConnectDisconnect() {
|
||||
blitz::network::TCPListener localserver;
|
||||
localserver.Listen(0, 1);
|
||||
blitz::network::TCPSocket socket;
|
||||
// Try to connect to a local server on port 8080
|
||||
blitz_test_assert(socket.Connect("localhost", localserver.GetListeningPort()));
|
||||
// Check if the socket status is Connected after connection
|
||||
blitz_test_assert(socket.GetStatus() == blitz::network::TCPSocket::Status::Connected);
|
||||
socket.Disconnect();
|
||||
// Check if the socket status is Disconnected after disconnection
|
||||
blitz_test_assert(socket.GetStatus() == blitz::network::TCPSocket::Status::Disconnected);
|
||||
}
|
||||
|
||||
// Test the listening and accepting of a TCPListener
|
||||
void Listener() {
|
||||
// Choose a random port
|
||||
std::uint16_t randomPort = blitz::utils::GetRandomInt(30000, 35000);
|
||||
|
||||
blitz::network::TCPListener listener;
|
||||
// Start listening on random port with a maximum of 10 connections
|
||||
blitz_test_assert(listener.Listen(randomPort, 10));
|
||||
// Check if the listener is listening on the correct port
|
||||
blitz_test_assert(listener.GetListeningPort() == randomPort);
|
||||
// Check if the listener has the correct maximum number of connections
|
||||
blitz_test_assert(listener.GetMaximumConnections() == 10);
|
||||
|
||||
blitz::network::TCPSocket socket;
|
||||
// Try to connect to the listener
|
||||
blitz_test_assert(socket.Connect("localhost", randomPort));
|
||||
blitz::network::TCPSocket newSocket;
|
||||
// Try to accept the connection from the socket
|
||||
blitz_test_assert(listener.Accept(newSocket));
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
ConnectDisconnect();
|
||||
Listener();
|
||||
return BLITZ_TEST_SUCCESSFUL;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "blitz/misc/Test.h"
|
||||
|
||||
#include "blitz/common/Vector.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
|
||||
using namespace blitz;
|
||||
|
||||
|
||||
@@ -2,6 +2,12 @@ add_rules("mode.debug", "mode.release", "mode.valgrind")
|
||||
|
||||
set_languages("c++17")
|
||||
|
||||
if is_mode("release") then
|
||||
set_warnings("all", "error")
|
||||
else
|
||||
set_warnings("all")
|
||||
end
|
||||
|
||||
includes("xmake/BlitzClient.lua")
|
||||
includes("xmake/BlitzServer.lua")
|
||||
includes("xmake/BlitzTest.lua")
|
||||
@@ -1,7 +1,7 @@
|
||||
includes("Blitz.lua")
|
||||
|
||||
add_requires("libsdl 2.28.3", {configs = {sdlmain = false}})
|
||||
add_requires("glbinding >= 3", "assimp", "nlohmann_json")
|
||||
add_requires("glew", "assimp", "nlohmann_json")
|
||||
|
||||
-- Client binary (default)
|
||||
target("BlitzClient")
|
||||
@@ -18,7 +18,7 @@ target("BlitzClient")
|
||||
|
||||
-- Libraries
|
||||
add_deps("Blitz")
|
||||
add_packages("libsdl", "glbinding", "assimp", "nlohmann_json")
|
||||
add_packages("libsdl", "glew", "assimp", "nlohmann_json")
|
||||
|
||||
add_includedirs("../libs", "../libs/imgui")
|
||||
add_files("../libs/imgui/**.cpp")
|
||||
|
||||
Reference in New Issue
Block a user