Compare commits
6 Commits
physics
...
gestionnai
| Author | SHA1 | Date | |
|---|---|---|---|
| cd4fb0a7ec | |||
| 582a66d4eb | |||
| 9a6642b1ad | |||
| d823dfa9d7 | |||
| 028715d3b5 | |||
| d4902214ae |
Binary file not shown.
BIN
assets/laser.wav
BIN
assets/laser.wav
Binary file not shown.
BIN
assets/sol.glb
BIN
assets/sol.glb
Binary file not shown.
@@ -253,7 +253,7 @@ class DataBuffer {
|
||||
* \brief Write a file into the buffer
|
||||
* \param fileName The name of the file to write to
|
||||
*/
|
||||
bool WriteFile(const std::string& fileName) const;
|
||||
bool WriteFile(const std::string& fileName);
|
||||
|
||||
/**
|
||||
* \brief Allocate the buffer on the heap
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* \file Defines.h
|
||||
* \brief File containing constants and typedefs
|
||||
*/
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -13,20 +13,8 @@ namespace game {
|
||||
/**
|
||||
* \typedef PlayerID
|
||||
* \brief Represents the identifier of a Player
|
||||
*/
|
||||
*/
|
||||
typedef std::uint8_t PlayerID;
|
||||
|
||||
/**
|
||||
* \enum GameState
|
||||
* \brief The states of the game
|
||||
*/
|
||||
enum GameState : std::uint8_t {
|
||||
gsNone = 0, /**< Default state */
|
||||
gsWaiting, /**< Waiting state if the number of players is less than 2 */
|
||||
gsPreparing, /**< Preparing state until the game start */
|
||||
gsGame, /**< Game state during the players can shoot and kill ... */
|
||||
gsEnd, /**< End state of the game : show the winner of the game and the leaderboard*/
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
} // namespace blitz
|
||||
|
||||
@@ -2,38 +2,17 @@
|
||||
|
||||
namespace blitz {
|
||||
|
||||
/**
|
||||
* \struct An exponential moving average smoother, or one pole lowpass filter
|
||||
* smoothes incoming data by attenutating sharp/sudden changes
|
||||
*/
|
||||
class EMASmoother {
|
||||
private:
|
||||
float Alpha;
|
||||
|
||||
float GetAlpha();
|
||||
void SetAlpha(float alpha);
|
||||
|
||||
public:
|
||||
/**
|
||||
* \brief the current output value of the smoother
|
||||
*/
|
||||
float Current;
|
||||
EMASmoother();
|
||||
/**
|
||||
* \brief behaves like `Tick(target, 1.0f)` but optimised
|
||||
*/
|
||||
void TickUnitT(float target);
|
||||
/**
|
||||
* \brief feed in the next value to the filter, and update `Current` accordingly
|
||||
* \param target the value in question
|
||||
* \param delta the time that has passed sinced the last value has been provided
|
||||
*/
|
||||
void Tick(float target, float delta);
|
||||
|
||||
/**
|
||||
* \brief set the amount of time it should take to reacha certain value, the higher this is
|
||||
* the "smoother the output signal"
|
||||
*/
|
||||
float GetAlpha();
|
||||
void SetAlpha(float alpha);
|
||||
void SetSmoothingTime(float t);
|
||||
};
|
||||
|
||||
|
||||
@@ -6,12 +6,8 @@
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "blitz/game/Listeners.h"
|
||||
#include "blitz/game/World.h"
|
||||
#include "blitz/misc/ObjectNotifier.h"
|
||||
#include "blitz/misc/Time.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace blitz {
|
||||
namespace game {
|
||||
@@ -22,6 +18,18 @@ namespace game {
|
||||
*/
|
||||
typedef std::map<PlayerID, Player> PlayerMap;
|
||||
|
||||
/**
|
||||
* \enum GameState
|
||||
* \brief The states of the game
|
||||
*/
|
||||
enum GameState : std::uint8_t {
|
||||
gsNone = 0, /**< Default state */
|
||||
gsWaiting, /**< Waiting state if the number of players is less than 2 */
|
||||
gsPreparing, /**< Preparing state until the game start */
|
||||
gsGame, /**< Game state during the players can shoot and kill ... */
|
||||
gsEnd, /**< End state of the game : show the winner of the game and the leaderboard*/
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief The game configuration
|
||||
* \struct GameConfig
|
||||
@@ -41,13 +49,12 @@ struct GameConfig {
|
||||
* \class Game
|
||||
* \brief Class representing a game
|
||||
*/
|
||||
class Game : public utils::ObjectNotifier<GameListener> {
|
||||
class Game {
|
||||
protected:
|
||||
PlayerMap m_Players;
|
||||
GameState m_GameState;
|
||||
utils::Timer m_GameTimer;
|
||||
GameConfig m_Config;
|
||||
std::unique_ptr<World> m_World;
|
||||
|
||||
public:
|
||||
/** \brief Default constructor */
|
||||
@@ -97,12 +104,6 @@ class Game : public utils::ObjectNotifier<GameListener> {
|
||||
return m_GameState;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the game state
|
||||
* \return The game state
|
||||
*/
|
||||
virtual void UpdateGameState(GameState newGameState, std::uint64_t timeRemaining);
|
||||
|
||||
/**
|
||||
* \brief Load the game configuration
|
||||
* \param config The game configuration to load
|
||||
@@ -138,13 +139,6 @@ class Game : public utils::ObjectNotifier<GameListener> {
|
||||
std::uint64_t GetGameStateRemainingTime() const {
|
||||
return m_GameTimer.GetTimeRemaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The world associated with this game
|
||||
*/
|
||||
const World* GetWorld() const {
|
||||
return m_World.get();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -21,19 +21,11 @@ class PlayerInputListener {
|
||||
virtual void OnLocalPlayerShoot(const Vec3f& position, float yaw, float pitch) {}
|
||||
};
|
||||
|
||||
class GameListener {
|
||||
public:
|
||||
virtual void OnPlayerJoin(game::PlayerID player) {}
|
||||
virtual void OnPlayerLeave(game::PlayerID player) {}
|
||||
virtual void OnGameStateUpdate(game::GameState newState) {}
|
||||
};
|
||||
|
||||
class ClientListener {
|
||||
public:
|
||||
virtual void OnTextChatReceived(const protocol::ColoredText& text) {}
|
||||
virtual void OnSpectatorChange(game::PlayerID player) {}
|
||||
virtual void OnPlayerShoot(PlayerID player, const Vec3f& position, float yaw, float pitch) {}
|
||||
virtual void OnClientPlayerJoin() {}
|
||||
virtual void OnGameConfigUpdate() {}
|
||||
virtual void OnGameJoin() {}
|
||||
virtual void OnGameLeave() {}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "blitz/common/Defines.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include "blitz/maths/Physics.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
@@ -43,7 +42,6 @@ struct PlayerStats {
|
||||
*/
|
||||
class Player {
|
||||
private:
|
||||
maths::AABB m_Hitbox;
|
||||
PlayerID m_ID;
|
||||
std::string m_Name;
|
||||
Vec3f m_Position;
|
||||
@@ -85,20 +83,6 @@ class Player {
|
||||
m_Name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the player's hitbox
|
||||
*/
|
||||
maths::AABB GetHitBox() const {
|
||||
return m_Hitbox + m_Position;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets the player's hitbox
|
||||
*/
|
||||
void SetHitBoxSize(const maths::AABB& aabb) {
|
||||
m_Hitbox = aabb;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the position of the player
|
||||
* \return The position of the player
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/game/Listeners.h"
|
||||
#include "blitz/maths/Physics.h"
|
||||
#include <vector>
|
||||
|
||||
namespace blitz {
|
||||
namespace game {
|
||||
|
||||
class Game;
|
||||
|
||||
class World {
|
||||
protected:
|
||||
Game* m_Game;
|
||||
std::vector<maths::AABB> m_AABBs;
|
||||
|
||||
public:
|
||||
World(Game* game);
|
||||
virtual ~World();
|
||||
|
||||
const std::vector<maths::AABB>& GetAABBs() const {
|
||||
return m_AABBs;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
} // namespace blitz
|
||||
@@ -128,32 +128,18 @@ T ReduceMax(const Vec3<T>& vect) {
|
||||
* \param v a vector
|
||||
* \return the (signed) minimal coordinate of the vector
|
||||
*/
|
||||
inline float ReduceFMinF(const Vec3f& v) {
|
||||
template <>
|
||||
inline float ReduceMin<float>(const Vec3f& v) {
|
||||
return std::fminf(std::fminf(v.x, v.y), v.z);
|
||||
}
|
||||
|
||||
inline Vec3f FmaF(const Vec3f& v, const Vec3f& a, const Vec3f& b) {
|
||||
return {
|
||||
std::fmaf(v.x, a.x, b.x),
|
||||
std::fmaf(v.y, a.y, b.y),
|
||||
std::fmaf(v.z, a.z, b.z),
|
||||
};
|
||||
}
|
||||
|
||||
inline Vec3d Fma(const Vec3d& v, const Vec3d& a, const Vec3d& b) {
|
||||
return {
|
||||
std::fma(v.x, a.x, b.x),
|
||||
std::fma(v.y, a.y, b.y),
|
||||
std::fma(v.z, a.z, b.z),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the (signed) maximal coordinate of the vector
|
||||
* \param v a vector
|
||||
* \return the (signed) maximal coordinate of the vector
|
||||
*/
|
||||
inline float ReduceFMaxF(const Vec3f& v) {
|
||||
template <>
|
||||
inline float ReduceMax<float>(const Vec3f& v) {
|
||||
return std::fmaxf(std::fmaxf(v.x, v.y), v.z);
|
||||
}
|
||||
|
||||
@@ -162,7 +148,8 @@ inline float ReduceFMaxF(const Vec3f& v) {
|
||||
* \param v a vector
|
||||
* \return the (signed) minimal coordinate of the vector
|
||||
*/
|
||||
inline double ReduceFMin(const Vec3d& v) {
|
||||
template <>
|
||||
inline double ReduceMin<double>(const Vec3d& v) {
|
||||
return std::fmin(std::fmin(v.x, v.y), v.z);
|
||||
}
|
||||
|
||||
@@ -171,7 +158,8 @@ inline double ReduceFMin(const Vec3d& v) {
|
||||
* \param v a vector
|
||||
* \return the (signed) maximal coordinate of the vector
|
||||
*/
|
||||
inline double ReduceFMax(const Vec3d& v) {
|
||||
template <>
|
||||
inline double ReduceMax<double>(const Vec3d& v) {
|
||||
return std::fmax(std::fmax(v.x, v.y), v.z);
|
||||
}
|
||||
|
||||
@@ -194,30 +182,13 @@ constexpr Vec3<T> Min(const Vec3<T>& self, const Vec3<T>& other) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the coordinate-wise minimum of the given vectors,
|
||||
* where a coordinate in the returned vector is NAN iff both of the two compared ones are NAN
|
||||
*
|
||||
* @tparam T
|
||||
* @param self
|
||||
* @param other
|
||||
* @return constexpr Vec3f
|
||||
*/
|
||||
constexpr Vec3f FMinF(const Vec3f& self, const Vec3f& other) {
|
||||
return {
|
||||
std::fminf(self.x, other.x),
|
||||
std::fminf(self.y, other.y),
|
||||
std::fminf(self.z, other.z),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the coordinate-wise maximum of the given vectors,
|
||||
* \brief returns the coordinate-wise maximum of the given vectors,
|
||||
* where a coordinate in the returned vector is NAN iff any of the two compared ones are NAN
|
||||
* \tparam T
|
||||
* \param self a vector
|
||||
* \param other an other vector
|
||||
* \return returns the coordinate-wise maximum of the given vectors,
|
||||
* where a coordinate in the returned vector is NAN iff any of the two compared ones are NAN
|
||||
*
|
||||
* @tparam T
|
||||
* @param self
|
||||
* @param other
|
||||
* @return constexpr Vec3
|
||||
*/
|
||||
template <typename T>
|
||||
constexpr Vec3<T> Max(const Vec3<T>& self, const Vec3<T>& other) {
|
||||
@@ -228,47 +199,8 @@ constexpr Vec3<T> Max(const Vec3<T>& self, const Vec3<T>& other) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the coordinate-wise maximum of the given vectors,
|
||||
* where a coordinate in the returned vector is NAN iff both of the two compared ones are NAN
|
||||
*
|
||||
* @tparam T
|
||||
* @param self
|
||||
* @param other
|
||||
* @return constexpr Vec3
|
||||
*/
|
||||
constexpr Vec3f FMaxF(const Vec3f& self, const Vec3f& other) {
|
||||
return {
|
||||
std::fmaxf(self.x, other.x),
|
||||
std::fmaxf(self.y, other.y),
|
||||
std::fmaxf(self.z, other.z),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief lane-wise copysign
|
||||
*/
|
||||
constexpr Vec3f CopysignF(const Vec3f& v, const Vec3f& signs) {
|
||||
return {
|
||||
std::copysignf(v.x, signs.x),
|
||||
std::copysignf(v.y, signs.y),
|
||||
std::copysignf(v.z, signs.z),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief lane-wise copysign
|
||||
*/
|
||||
constexpr Vec3d Copysign(const Vec3d& v, const Vec3d& signs) {
|
||||
return {
|
||||
std::copysign(v.x, signs.x),
|
||||
std::copysign(v.y, signs.y),
|
||||
std::copysign(v.z, signs.z),
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Matrices //
|
||||
// Matricies //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
@@ -418,16 +350,5 @@ Mat4f Rotate(const Vec3f& angles);
|
||||
*/
|
||||
Mat4f Rotate(float angle, Vec3f axis);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns the unit vector correspond to the yaw and pitch
|
||||
* \param yaw Angle in radians
|
||||
* \param pitch Angle in radians
|
||||
*/
|
||||
Vec3f GetDirectionVectorFromRotation(float yaw, float pitch);
|
||||
|
||||
} // namespace maths
|
||||
} // namespace blitz
|
||||
|
||||
@@ -1,149 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* \file Physics.h
|
||||
* \brief Physics logic
|
||||
*/
|
||||
|
||||
#include "blitz/maths/Maths.h"
|
||||
#include <optional>
|
||||
#include "blitz/maths/Vector.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace maths {
|
||||
|
||||
/**
|
||||
* \enum Axis
|
||||
* \brief represents an axis in 3-dimensional space
|
||||
*/
|
||||
enum Axis : std::size_t { aX = 0, aY, aZ };
|
||||
|
||||
/**
|
||||
* \brief encodes the movement an entity must perform, in an environment containing other
|
||||
* entitis it may collide with
|
||||
*/
|
||||
struct CollisionData {
|
||||
/**
|
||||
* \brief the effective movement the entity can/should perform, immediately
|
||||
*/
|
||||
Vec3f delta;
|
||||
/**
|
||||
* \brief the direction of "slide" along a side of a bounding
|
||||
* box, this is 0 if no collisions occured
|
||||
*/
|
||||
Vec3f slide;
|
||||
struct Ray {
|
||||
Vec3f origin;
|
||||
Vec3f direction;
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct IntersectionData
|
||||
* \brief Intermediate data encoding an intersection between a Ray/AABB and an AABB
|
||||
*/
|
||||
struct IntersectionData {
|
||||
/**
|
||||
* \brief by how much to translate before intersecting with the AABB
|
||||
*/
|
||||
float distance;
|
||||
/**
|
||||
* \brief the axis along which the collision happens, used to solve sliding requirements
|
||||
*/
|
||||
Axis axis;
|
||||
|
||||
/**
|
||||
* \brief Returns the movements that the entity must perform. It is advised to make sure
|
||||
* `0.0f <= distance <= 1.0f` as this would return incoherent data
|
||||
* \pre `0.0f <= distance <= 1.0f`
|
||||
* \param dir
|
||||
* \return
|
||||
*/
|
||||
CollisionData ToCollision(const Vec3f& dir) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct AABB
|
||||
* \brief an Axis Aligned Bounding Box, see wikipedia for more
|
||||
*/
|
||||
struct AABB {
|
||||
Vec3f from;
|
||||
Vec3f to;
|
||||
|
||||
/**
|
||||
* \return A vector representing the center of mass of the box
|
||||
*/
|
||||
inline Vec3f Center() const;
|
||||
|
||||
/**
|
||||
* \return The same box but all the coordinates in `from` are less than their
|
||||
* counterparts in `to`.
|
||||
*/
|
||||
AABB Direct() const;
|
||||
|
||||
/**
|
||||
* \brief Enlarges this box along each axis by the length of the box along said axis
|
||||
* \param with
|
||||
* \return The new, big, box
|
||||
*
|
||||
*/
|
||||
AABB Enlarge(const AABB& with) const;
|
||||
|
||||
AABB operator+(const Vec3f& offset) const;
|
||||
|
||||
AABB operator+=(const Vec3f& offset);
|
||||
|
||||
/**
|
||||
* \brief checks if this box overlaps with another one
|
||||
* \param aabb
|
||||
* \return whether this box overlaps with another one
|
||||
*/
|
||||
bool OverlapsWith(const AABB& aabb) const;
|
||||
|
||||
/**
|
||||
* \brief Given this box is to be offset by some vector colinear to dir,
|
||||
* this function behave exactly like Ray::Intersection
|
||||
* \param aabb
|
||||
* \param dir
|
||||
* \return
|
||||
*/
|
||||
std::optional<IntersectionData> Intersection(const AABB& aabb, const Vec3f& dir) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct Ray
|
||||
* \brief represents a (half-)line
|
||||
*/
|
||||
struct Ray {
|
||||
/**
|
||||
* \brief the origin/start/initial point of the line
|
||||
*/
|
||||
Vec3f origin;
|
||||
/**
|
||||
* \brief the direction of the line
|
||||
*/
|
||||
Vec3f direction;
|
||||
inline AABB operator+(const AABB& aabb, const Vec3f& offset) {
|
||||
AABB result = aabb;
|
||||
result.from += offset;
|
||||
result.to += offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Note that t isn't necessarily positive
|
||||
* \param t
|
||||
* \return `origin` + `direction` * `t`
|
||||
*/
|
||||
Vec3f operator()(float t) const;
|
||||
float Distance(const Ray& ray, const AABB& aabb);
|
||||
|
||||
/**
|
||||
* \brief Is essentially Intersection(aabb).distance >= 0.0f
|
||||
* \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.
|
||||
*/
|
||||
bool Intersects(const AABB& aabb) const;
|
||||
|
||||
/**
|
||||
* \brief The `distance` field of the returned value is smallest number t
|
||||
* (in absolute value), if it exists, such that `ray(t)` is in `aabb`. otherwise
|
||||
* a quiet `NaN` is returned. The `axis` field is the axis to along
|
||||
* which `ray` intersects/collides with `aabb`
|
||||
*/
|
||||
std::optional<IntersectionData> Intersection(const AABB& aabb) const;
|
||||
};
|
||||
bool Intersects(const Ray& ray, const AABB& aabb);
|
||||
|
||||
} // namespace maths
|
||||
} // namespace blitz
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
namespace blitz {
|
||||
@@ -47,34 +48,6 @@ struct Vec3 {
|
||||
};
|
||||
|
||||
constexpr Vec3(T X = 0, T Y = 0, T Z = 0) : x(X), y(Y), z(Z) {}
|
||||
|
||||
static Vec3 splat(T val) {
|
||||
return Vec3(val, val, val);
|
||||
}
|
||||
|
||||
const T* data() const {
|
||||
return reinterpret_cast<const T*>(this);
|
||||
}
|
||||
|
||||
T* data() {
|
||||
return reinterpret_cast<T*>(this);
|
||||
}
|
||||
|
||||
const T& at(std::size_t index) const {
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
T& at(std::size_t index) {
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
const T& operator[](std::size_t index) const {
|
||||
return at(index);
|
||||
}
|
||||
|
||||
T& operator[](std::size_t index) {
|
||||
return at(index);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -123,6 +96,10 @@ using Vec4d = Vec4<double>;
|
||||
|
||||
using Color = Vec3uc;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Vec2
|
||||
|
||||
template <typename T>
|
||||
@@ -167,6 +144,10 @@ constexpr Vec2<T> operator*(T mult, const Vec2<T>& vect) {
|
||||
return vect * mult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Vec3
|
||||
|
||||
template <typename T>
|
||||
@@ -245,6 +226,11 @@ Vec3<T>& operator/=(Vec3<T>& vect, const Vec3<T>& 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
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -45,7 +45,7 @@ class ObjectNotifier {
|
||||
* \brief Notify listeners that were bound
|
||||
*/
|
||||
template <typename Func, typename... Args>
|
||||
void NotifyListeners(Func function, Args... args) const {
|
||||
void NotifyListeners(Func function, Args... args) {
|
||||
for (Listener* listener : m_Listeners)
|
||||
std::bind(function, listener, args...)();
|
||||
}
|
||||
|
||||
@@ -3,31 +3,19 @@
|
||||
#include "blitz/game/Listeners.h"
|
||||
#include "client/audio/AudioListener.h"
|
||||
#include "client/audio/AudioSource.h"
|
||||
#include <map>
|
||||
|
||||
namespace blitz {
|
||||
|
||||
class Client;
|
||||
|
||||
namespace game {
|
||||
class Player;
|
||||
} // namespace game
|
||||
|
||||
|
||||
namespace audio {
|
||||
|
||||
struct PlayerSound {
|
||||
AudioSourcePtr m_Laser;
|
||||
};
|
||||
|
||||
class AudioManager : public game::ClientListener, public game::GameListener {
|
||||
class AudioManager : public game::ClientListener {
|
||||
private:
|
||||
Client* m_Client;
|
||||
game::Player* m_Player;
|
||||
AudioListener m_Listener;
|
||||
AudioSourcePtr m_MenuMusic;
|
||||
AudioBufferPtr m_LaserSound;
|
||||
std::map<game::PlayerID, PlayerSound> m_PlayerSources;
|
||||
std::vector<AudioSourcePtr> m_Sources;
|
||||
|
||||
public:
|
||||
AudioManager(Client* client);
|
||||
@@ -35,20 +23,9 @@ class AudioManager : public game::ClientListener, public game::GameListener {
|
||||
|
||||
virtual void OnGameJoin() override;
|
||||
virtual void OnGameLeave() override;
|
||||
virtual void OnClientPlayerJoin() override;
|
||||
virtual void OnPlayerShoot(game::PlayerID player, const Vec3f& position, float yaw, float pitch) override;
|
||||
virtual void OnPlayerJoin(game::PlayerID player) override;
|
||||
virtual void OnPlayerLeave(game::PlayerID player) override;
|
||||
|
||||
void SetGlobalVolume(float volume);
|
||||
|
||||
void Update();
|
||||
|
||||
private:
|
||||
void InitSounds();
|
||||
AudioSourcePtr InitSourceFromFile(const std::string& fileName);
|
||||
AudioSourcePtr InitSourceFromBuffer(const AudioBufferPtr& buffer);
|
||||
AudioBufferPtr InitBufferFromFile(const std::string& fileName);
|
||||
void InitMainMenuMusic();
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
typedef std::shared_ptr<AudioBuffer> AudioBufferPtr;
|
||||
typedef std::unique_ptr<AudioBuffer> AudioBufferPtr;
|
||||
|
||||
class AudioSource : NonCopyable {
|
||||
private:
|
||||
@@ -27,8 +27,7 @@ class AudioSource : NonCopyable {
|
||||
void SetDirection(const Vec3f& a_Direction);
|
||||
void SetVelocity(const Vec3f& a_Velocity);
|
||||
void SetLooping(bool a_Looping);
|
||||
void SetRelative(bool a_Relative);
|
||||
void SetBuffer(const AudioBufferPtr& a_Buffer);
|
||||
void SetBuffer(AudioBufferPtr&& a_Buffer);
|
||||
|
||||
SourceState GetSourceState() const;
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
* \brief File containing the blitz::Display class
|
||||
*/
|
||||
|
||||
#include "client/display/InputManager.h"
|
||||
#include "client/display/PlayerController.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -38,9 +36,7 @@ class Display {
|
||||
bool m_FullScreen;
|
||||
|
||||
Client* m_Client;
|
||||
input::InputManager& m_InputManager;
|
||||
std::unique_ptr<gui::BlitzGui> m_BlitzGui;
|
||||
input::PlayerController m_PlayerController;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -49,33 +45,28 @@ class Display {
|
||||
* \param height The height of the window
|
||||
* \param windowName The name of the window
|
||||
* \param client The client
|
||||
* \param inputManager The InputManager
|
||||
*/
|
||||
Display(int width, int height, const std::string& windowName, Client* client, input::InputManager& inputManager);
|
||||
Display(int width, int height, const std::string& windowName, Client* client);
|
||||
~Display();
|
||||
|
||||
/**
|
||||
* \brief Return whether the display has been created
|
||||
*/
|
||||
bool Create();
|
||||
|
||||
/**
|
||||
* \brief Poll the events
|
||||
* \note This function should be called at the beginning of the main loop
|
||||
*/
|
||||
void PollEvents();
|
||||
|
||||
/**
|
||||
* \brief Update the display
|
||||
* \note Swap the buffers
|
||||
*/
|
||||
void Update();
|
||||
|
||||
/**
|
||||
* \brief Render the display (ImGui)
|
||||
*/
|
||||
void Render();
|
||||
|
||||
/**
|
||||
* \brief Destroy the display (Not your mother's display)
|
||||
*/
|
||||
@@ -90,24 +81,15 @@ class Display {
|
||||
* \brief Return widht/height ratio
|
||||
*/
|
||||
float GetAspectRatio();
|
||||
|
||||
/**
|
||||
* \brief Return the window width
|
||||
*/
|
||||
int GetWindowWidth();
|
||||
|
||||
/**
|
||||
* \brief Return the window height
|
||||
*/
|
||||
int GetWindowHeight();
|
||||
|
||||
/**
|
||||
* \brief Return the player controller
|
||||
*/
|
||||
input::PlayerController& GetPlayerController() {
|
||||
return m_PlayerController;
|
||||
}
|
||||
|
||||
private:
|
||||
void InitImGui();
|
||||
};
|
||||
|
||||
@@ -1,30 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/misc/ObjectNotifier.h"
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <functional>
|
||||
|
||||
namespace blitz {
|
||||
namespace input {
|
||||
namespace InputManager {
|
||||
|
||||
class InputListener {
|
||||
public:
|
||||
virtual void OnKeyDown(int imguiKey) {}
|
||||
virtual void OnMouseMove(int deltaX, int deltaY) {}
|
||||
};
|
||||
typedef std::function<void(int)> KeyDownCallback;
|
||||
typedef std::function<void(int, int)> MouseMoveCallback;
|
||||
|
||||
class InputManager : public utils::ObjectNotifier<InputListener> {
|
||||
private:
|
||||
bool m_MouseInputGrabbed;
|
||||
void BindKeyDownCallback(const KeyDownCallback&);
|
||||
void BindMouseMoveCallback(const MouseMoveCallback&);
|
||||
void ProcessEvent(SDL_Event& event);
|
||||
void GrabMouse(bool grabInput);
|
||||
bool MouseGrabbed();
|
||||
|
||||
public:
|
||||
InputManager() : m_MouseInputGrabbed(false) {}
|
||||
virtual ~InputManager() {}
|
||||
|
||||
void ProcessEvent(SDL_Event& event) const;
|
||||
void GrabMouse(bool grabInput);
|
||||
bool MouseGrabbed() const;
|
||||
};
|
||||
|
||||
} // namespace input
|
||||
} // namespace InputManager
|
||||
} // namespace blitz
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "blitz/game/Listeners.h"
|
||||
#include "blitz/misc/ObjectNotifier.h"
|
||||
#include "blitz/misc/Time.h"
|
||||
#include "client/display/InputManager.h"
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -28,11 +27,10 @@ namespace input {
|
||||
* \details This class is responsible for handling player input and sending it to the server.
|
||||
* It also handles the player's velocity and position.
|
||||
*/
|
||||
class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener>, game::ClientListener, InputListener {
|
||||
class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener>, game::ClientListener {
|
||||
private:
|
||||
game::Player* m_Player;
|
||||
Client* m_Client;
|
||||
input::InputManager& m_InputManager;
|
||||
utils::CooldownTimer<float> m_ShootTimer{1.0f};
|
||||
EMASmoother m_DxSmoother;
|
||||
EMASmoother m_DySmoother;
|
||||
@@ -47,8 +45,7 @@ class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener>
|
||||
/**
|
||||
* \brief Default constructor
|
||||
*/
|
||||
PlayerController(Client* client, input::InputManager& inputManager);
|
||||
virtual ~PlayerController();
|
||||
PlayerController(Client* client);
|
||||
|
||||
/**
|
||||
* \brief Update things like player position and velocity.
|
||||
@@ -56,16 +53,27 @@ class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener>
|
||||
void Update(float delta);
|
||||
|
||||
virtual void OnGameConfigUpdate() override;
|
||||
virtual void OnClientPlayerJoin() override;
|
||||
virtual void OnGameLeave() override;
|
||||
|
||||
virtual void OnMouseMove(int, int) override;
|
||||
/**
|
||||
* \brief Set the player that this controller is attached to.
|
||||
* \param a_Player The player to attach to.
|
||||
*/
|
||||
void SetAttachedPlayer(game::Player* a_Player) {
|
||||
m_Player = a_Player;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the player that this controller is attached to.
|
||||
* \return The player that this controller is attached to.
|
||||
*/
|
||||
game::Player* GetAttachedPlayer() {
|
||||
return m_Player;
|
||||
}
|
||||
|
||||
private:
|
||||
void UpdateShootTimer(int bpm);
|
||||
void MouseMotionEvent(int, int);
|
||||
void UpdatePosition(float delta);
|
||||
void ApplyForce(const Vec3f& f, float delta);
|
||||
void ApplyGravity(float delta);
|
||||
};
|
||||
|
||||
} // namespace input
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/game/World.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace client {
|
||||
|
||||
class ClientGame;
|
||||
|
||||
class ClientWorld : public game::World {
|
||||
public:
|
||||
ClientWorld(ClientGame* game);
|
||||
virtual ~ClientWorld() {}
|
||||
|
||||
private:
|
||||
void LoadAABBs();
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace blitz
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
#include "client/display/InputManager.h"
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -14,7 +13,7 @@ class BlitzGui : public GuiWidget {
|
||||
enum SubMenu { Main = 0 };
|
||||
|
||||
public:
|
||||
BlitzGui(Client* client, input::InputManager& inputManager);
|
||||
BlitzGui(Client* client);
|
||||
|
||||
virtual void Render() override;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
#include "client/display/InputManager.h"
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -10,11 +9,8 @@ class Client;
|
||||
namespace gui {
|
||||
|
||||
class CreateGameMenu : public GuiWidget {
|
||||
private:
|
||||
input::InputManager& m_InputManager;
|
||||
|
||||
public:
|
||||
CreateGameMenu(GuiWidget* parent, Client* client, input::InputManager& inputManager);
|
||||
CreateGameMenu(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {}
|
||||
|
||||
virtual void Render() override;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "GuiWidget.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/display/InputManager.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -20,15 +19,13 @@ class GameChatGui : public GuiWidget, game::ClientListener {
|
||||
bool ScrollToBottom = false;
|
||||
bool AutoScroll = true;
|
||||
float m_ChatDisplay = 0;
|
||||
input::InputManager& m_InputManager;
|
||||
|
||||
|
||||
void Draw(const char* title, bool* p_open);
|
||||
void DrawMini(const char* title, bool* p_open);
|
||||
|
||||
public:
|
||||
GameChatGui(GuiWidget* parent, Client* client, input::InputManager& inputManager);
|
||||
virtual ~GameChatGui();
|
||||
GameChatGui(GuiWidget* parent, Client* client);
|
||||
|
||||
virtual void OnTextChatReceived(const protocol::ColoredText& text) override;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
#include "client/display/InputManager.h"
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -10,11 +9,8 @@ class Client;
|
||||
namespace gui {
|
||||
|
||||
class JoinGameMenu : public GuiWidget {
|
||||
private:
|
||||
input::InputManager& m_InputManager;
|
||||
|
||||
public:
|
||||
JoinGameMenu(GuiWidget* parent, Client* client, input::InputManager& inputManager);
|
||||
JoinGameMenu(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {}
|
||||
|
||||
virtual void Render() override;
|
||||
};
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
#include "blitz/game/Listeners.h"
|
||||
|
||||
namespace blitz {
|
||||
|
||||
class Client;
|
||||
|
||||
namespace input {
|
||||
class InputManager;
|
||||
} // namespace input
|
||||
|
||||
namespace gui {
|
||||
|
||||
class MainMenu : public GuiWidget, public game::ClientListener {
|
||||
class MainMenu : public GuiWidget {
|
||||
private:
|
||||
enum SubMenu { CREATE_MENU = 0, JOIN_MENU, OPTION_MENU };
|
||||
|
||||
input::InputManager& m_InputManager;
|
||||
|
||||
public:
|
||||
MainMenu(Client* client, input::InputManager& inputManager);
|
||||
virtual ~MainMenu();
|
||||
|
||||
virtual void OnGameLeave() override;
|
||||
MainMenu(Client* client);
|
||||
|
||||
virtual void Render() override;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "GuiWidget.h"
|
||||
#include "blitz/misc/Time.h"
|
||||
#include "client/config/BlitzConfig.h"
|
||||
#include "client/display/InputManager.h"
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
@@ -13,7 +12,7 @@ class Client;
|
||||
|
||||
namespace gui {
|
||||
|
||||
class OptionsMenu : public GuiWidget, public input::InputListener {
|
||||
class OptionsMenu : public GuiWidget {
|
||||
private:
|
||||
bool m_ShowFPS;
|
||||
bool m_VSync;
|
||||
@@ -21,15 +20,13 @@ class OptionsMenu : public GuiWidget, public input::InputListener {
|
||||
bool m_KeyPopupShouldClose;
|
||||
utils::Timer m_Timer{100};
|
||||
KeyAction m_CurrentAction;
|
||||
input::InputManager& m_InputManager;
|
||||
|
||||
public:
|
||||
OptionsMenu(GuiWidget* parent, Client* client, input::InputManager& inputManager);
|
||||
virtual ~OptionsMenu();
|
||||
OptionsMenu(GuiWidget* parent, Client* client);
|
||||
|
||||
virtual void Render() override;
|
||||
|
||||
virtual void OnKeyDown(int key) override;
|
||||
void OnKeyEvent(int key);
|
||||
|
||||
private:
|
||||
std::string GetKeyActionCodeName(KeyAction);
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
#include "client/display/InputManager.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
class ServerGui : public GuiWidget {
|
||||
private:
|
||||
input::InputManager& m_InputManager;
|
||||
|
||||
public:
|
||||
ServerGui(GuiWidget* parent, Client* client, input::InputManager& inputManager);
|
||||
ServerGui(GuiWidget* parent, Client* client);
|
||||
|
||||
virtual void Render() override;
|
||||
};
|
||||
|
||||
@@ -37,7 +37,6 @@ class BulletRenderer {
|
||||
void AddBullet(const Vec3f& origin, float yaw, float pitch, bool firstPersson);
|
||||
void Update(float delta);
|
||||
void Render();
|
||||
void Clear();
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -29,14 +29,14 @@ class MainRenderer : public game::ClientListener, public game::PlayerInputListen
|
||||
std::unique_ptr<shader::EntityShader> m_EntityShader;
|
||||
std::unique_ptr<shader::WorldShader> m_WorldShader;
|
||||
std::unique_ptr<shader::GunShader> m_GunShader;
|
||||
input::PlayerController m_PlayerController;
|
||||
unsigned int m_Texture;
|
||||
float m_ShootTime;
|
||||
Camera m_Camera;
|
||||
BulletRenderer m_BulletRenderer;
|
||||
input::PlayerController& m_PlayerController;
|
||||
|
||||
public:
|
||||
MainRenderer(Client* client, input::PlayerController& playerController);
|
||||
MainRenderer(Client* client);
|
||||
~MainRenderer();
|
||||
|
||||
virtual void OnSpectatorChange(game::PlayerID player) override;
|
||||
@@ -44,7 +44,6 @@ class MainRenderer : public game::ClientListener, public game::PlayerInputListen
|
||||
virtual void OnLocalPlayerShoot(const Vec3f& position, float yaw, float pitch) override;
|
||||
|
||||
virtual void OnGameConfigUpdate() override;
|
||||
virtual void OnGameLeave() override;
|
||||
|
||||
void Update();
|
||||
void Render();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/maths/Physics.h"
|
||||
#include "client/render/loader/GLLoader.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -17,7 +16,5 @@ struct Model {
|
||||
|
||||
Model LoadModel(const std::string& fileName);
|
||||
|
||||
std::vector<maths::AABB> LoadModelAABBs(const std::string& fileName);
|
||||
|
||||
} // namespace ModelLoader
|
||||
} // namespace blitz
|
||||
|
||||
@@ -44,8 +44,6 @@ class Server {
|
||||
std::thread m_Thread;
|
||||
bool m_ServerRunning;
|
||||
|
||||
game::PlayerID m_FreePlayerID;
|
||||
|
||||
public:
|
||||
/**
|
||||
* \brief Constructor
|
||||
|
||||
@@ -74,7 +74,7 @@ class ServerGame : public game::Game {
|
||||
* \param gameState The game state
|
||||
* \param duration The duration in milliseconds
|
||||
*/
|
||||
virtual void UpdateGameState(game::GameState gameState, std::uint64_t duration) override;
|
||||
void SetGameState(game::GameState gameState, std::uint64_t duration);
|
||||
|
||||
/**
|
||||
* \brief Get the server duration
|
||||
@@ -97,7 +97,6 @@ class ServerGame : public game::Game {
|
||||
void StartGame(); // when at least 2 players joined
|
||||
void CancelGame(); // when not enough players are left
|
||||
void ResetPlayerStats();
|
||||
void InitGameConfig();
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct SDL_Window;
|
||||
class SDL_Window;
|
||||
struct SDL_Renderer;
|
||||
typedef union SDL_Event SDL_Event;
|
||||
|
||||
|
||||
@@ -2,19 +2,17 @@
|
||||
#include "client/Client.h"
|
||||
#include "client/audio/AudioManager.h"
|
||||
#include "client/display/Display.h"
|
||||
#include "client/display/InputManager.h"
|
||||
#include "client/render/MainRenderer.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
blitz::Client client;
|
||||
blitz::input::InputManager inputManager;
|
||||
blitz::Display display(1920, 1080, "BlitzKrieg", &client, inputManager);
|
||||
blitz::Display display(1920, 1080, "BlitzKrieg", &client);
|
||||
|
||||
if (!display.Create())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
blitz::render::MainRenderer renderer(&client, display.GetPlayerController());
|
||||
blitz::render::MainRenderer renderer(&client);
|
||||
blitz::audio::AudioManager audioManager(&client);
|
||||
blitz::network::NetworkInitializer network;
|
||||
|
||||
@@ -22,7 +20,6 @@ int main(int argc, char** argv) {
|
||||
client.Update();
|
||||
display.PollEvents();
|
||||
renderer.Update();
|
||||
audioManager.Update();
|
||||
renderer.Render();
|
||||
display.Render();
|
||||
display.Update();
|
||||
|
||||
@@ -85,7 +85,7 @@ bool DataBuffer::ReadFile(const std::string& fileName) {
|
||||
return m_Buffer.size() > 0;
|
||||
}
|
||||
|
||||
bool DataBuffer::WriteFile(const std::string& fileName) const {
|
||||
bool DataBuffer::WriteFile(const std::string& fileName) {
|
||||
try {
|
||||
std::ofstream file(fileName, std::ostream::binary);
|
||||
file.write(reinterpret_cast<const char*>(m_Buffer.data()), static_cast<std::streamsize>(m_Buffer.size()));
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "blitz/game/Game.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace blitz {
|
||||
namespace game {
|
||||
@@ -26,19 +25,10 @@ void Game::AddPlayer(PlayerID player, const std::string& name) {
|
||||
static float MAX_HP = 100;
|
||||
|
||||
game::Player newPlayer{player};
|
||||
static const maths::AABB PLAYER_BASE_AABB = {Vec3f{-0.5f, -0.9f, -0.5f}, Vec3f{0.5f, 0.9f, 0.5f}};
|
||||
newPlayer.SetHitBoxSize(PLAYER_BASE_AABB);
|
||||
newPlayer.SetPosition({
|
||||
0.0f,
|
||||
std::fabs(PLAYER_BASE_AABB.to.y - PLAYER_BASE_AABB.from.y) * 10.0f,
|
||||
0.0f
|
||||
});
|
||||
newPlayer.SetName(name);
|
||||
newPlayer.SetHP(MAX_HP);
|
||||
|
||||
GetPlayers().insert({player, newPlayer});
|
||||
|
||||
NotifyListeners(&GameListener::OnPlayerJoin, player);
|
||||
}
|
||||
|
||||
void Game::RemovePlayer(PlayerID player) {
|
||||
@@ -47,17 +37,8 @@ void Game::RemovePlayer(PlayerID player) {
|
||||
if (it == GetPlayers().end())
|
||||
return;
|
||||
|
||||
NotifyListeners(&GameListener::OnPlayerLeave, player);
|
||||
|
||||
GetPlayers().erase(it);
|
||||
}
|
||||
|
||||
void Game::UpdateGameState(GameState newGameState, std::uint64_t timeRemaining) {
|
||||
m_GameState = newGameState;
|
||||
m_GameTimer.SetInterval(timeRemaining);
|
||||
m_GameTimer.Reset();
|
||||
NotifyListeners(&GameListener::OnGameStateUpdate, newGameState);
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
} // namespace blitz
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#include "blitz/game/World.h"
|
||||
|
||||
#include "blitz/game/Game.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace game {
|
||||
|
||||
World::World(Game* game) : m_Game(game) {}
|
||||
|
||||
World::~World() {}
|
||||
|
||||
} // namespace game
|
||||
} // namespace blitz
|
||||
@@ -5,20 +5,15 @@
|
||||
namespace blitz {
|
||||
namespace maths {
|
||||
|
||||
Mat4f Perspective(float fovY, float invAspectRatio, float zNear, float zFar) {
|
||||
|
||||
static const float FRAC_PI_2 = 1.5707963267948966;
|
||||
|
||||
const float cotanHalfFovy = -std::tan(std::fmaf(fovY, 0.5f, FRAC_PI_2));
|
||||
|
||||
float neg_i_z_diff = -1.0f / (zFar - zNear);
|
||||
Mat4f Perspective(float fovY, float aspectRatio, float zNear, float zFar) {
|
||||
const float tanHalfFovy = std::tan(fovY / 2.0f);
|
||||
|
||||
Mat4f result{};
|
||||
result.x0 = cotanHalfFovy * invAspectRatio;
|
||||
result.y1 = cotanHalfFovy;
|
||||
result.z2 = (zFar + zNear) * neg_i_z_diff;
|
||||
result.x0 = 1.0f / (aspectRatio * tanHalfFovy);
|
||||
result.y1 = 1.0f / (tanHalfFovy);
|
||||
result.z2 = -(zFar + zNear) / (zFar - zNear);
|
||||
result.z3 = -1.0f;
|
||||
result.w2 = 2.0f * zFar * zNear * neg_i_z_diff;
|
||||
result.w2 = -(2.0f * zFar * zNear) / (zFar - zNear);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -176,13 +171,5 @@ Mat4f Rotate(float angle, Vec3f axis) {
|
||||
return mat;
|
||||
}
|
||||
|
||||
Vec3f GetDirectionVectorFromRotation(float yaw, float pitch) {
|
||||
return {
|
||||
std::cos(yaw) * std::cos(pitch),
|
||||
std::sin(pitch),
|
||||
std::sin(yaw) * std::cos(pitch),
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace maths
|
||||
} // namespace blitz
|
||||
|
||||
109
src/blitz/maths/Physics.cpp
Normal file → Executable file
109
src/blitz/maths/Physics.cpp
Normal file → Executable file
@@ -1,112 +1,67 @@
|
||||
#include "blitz/maths/Physics.h"
|
||||
#include "blitz/maths/Maths.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace blitz {
|
||||
namespace maths {
|
||||
|
||||
AABB AABB::Enlarge(const AABB& with) const {
|
||||
const Vec3f dir = 0.5f * (with.to - with.from);
|
||||
/**
|
||||
* @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) {
|
||||
|
||||
return AABB{
|
||||
from - dir,
|
||||
to + dir,
|
||||
};
|
||||
}
|
||||
|
||||
AABB AABB::Direct() const {
|
||||
return AABB{Min(from, to), Max(from, to)};
|
||||
}
|
||||
|
||||
Vec3f AABB::Center() const {
|
||||
return (from + to) * 0.5f;
|
||||
}
|
||||
|
||||
AABB AABB::operator+(const Vec3f& offset) const {
|
||||
return AABB{from + offset, to + offset};
|
||||
}
|
||||
|
||||
AABB AABB::operator+=(const Vec3f& offset) {
|
||||
*this = *this + offset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool AABB::OverlapsWith(const AABB& aabb) const {
|
||||
|
||||
return RangesOverlapping(from.x, to.x, aabb.from.x, aabb.to.x) &&
|
||||
RangesOverlapping(from.y, to.y, aabb.from.y, aabb.to.y) &&
|
||||
RangesOverlapping(from.z, to.z, aabb.from.z, aabb.to.z);
|
||||
}
|
||||
|
||||
std::optional<IntersectionData> AABB::Intersection(const AABB& aabb, const Vec3f& dir) const {
|
||||
return Ray { Center(), dir }.Intersection(aabb.Enlarge(*this));
|
||||
}
|
||||
|
||||
Vec3f Ray::operator()(float t) const {
|
||||
return FmaF(Vec3f::splat(t), direction, origin);
|
||||
}
|
||||
|
||||
std::optional<IntersectionData> Ray::Intersection(const AABB& aabb) const {
|
||||
|
||||
// This function calculates smallest interval I = ] tmin, tmax [,
|
||||
// such that for all t in I ray(t) is in the AABB, now, if tmin > tmax
|
||||
// there is no such t, i.e. the ray never intersects with the 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
|
||||
AABB directed = aabb.Direct();
|
||||
Vec3f& l = directed.from;
|
||||
Vec3f& r = directed.to;
|
||||
Vec3f l = Min(aabb.from, aabb.to);
|
||||
Vec3f r = Max(aabb.to, aabb.from);
|
||||
|
||||
// m - o < t * d < M - o
|
||||
l -= origin;
|
||||
r -= origin;
|
||||
l -= ray.origin;
|
||||
r -= ray.origin;
|
||||
|
||||
// (m - o) / d < t < (M - o) / d
|
||||
l /= direction;
|
||||
r /= direction;
|
||||
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;
|
||||
|
||||
const float tmin = ReduceFMaxF(l);
|
||||
const float tmax = ReduceFMinF(r);
|
||||
float tmin = ReduceMax(l);
|
||||
float tmax = ReduceMin(r);
|
||||
|
||||
// Since Min propagates NANs and ReduceFMinF doesn't, and since NAN != <any float>
|
||||
// the inequality becomes ignored for coordinates where a NaN is involved
|
||||
// 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 0.0, which is technically the correct result
|
||||
if (tmin <= tmax && tmax > 0.0f) {
|
||||
|
||||
Axis axis = Axis::aZ;
|
||||
for (std::size_t i = 2; i >= 0; i--) {
|
||||
Axis this_axis = Axis(i);
|
||||
if (l[this_axis] == tmin) {
|
||||
axis = this_axis;
|
||||
break;
|
||||
}
|
||||
// in which case this returns -1
|
||||
if (tmax >= 0.0f && tmin <= tmax) {
|
||||
return std::fmaxf(tmin, 0.0f);
|
||||
}
|
||||
|
||||
const float dist = std::fmaxf(0.0f, tmin);
|
||||
return std::make_optional(IntersectionData { dist, axis });
|
||||
}
|
||||
return std::nullopt;
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
bool Ray::Intersects(const AABB& aabb) const {
|
||||
auto data = Intersection(aabb);
|
||||
return data.has_value() && data->distance >= 0.0f;
|
||||
bool Intersects(const AABB& aabb1, const AABB& aabb2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CollisionData IntersectionData::ToCollision(const Vec3f& dir) const {
|
||||
Vec3f new_dir = dir;
|
||||
new_dir[axis] = 0.0f;
|
||||
return CollisionData{dir * (distance - 0.07f), new_dir * (1.0f - distance)};
|
||||
bool Intersects(const Ray& ray, const AABB& aabb) {
|
||||
return Distance(ray, aabb) >= 0.0f;
|
||||
}
|
||||
|
||||
} // namespace maths
|
||||
|
||||
@@ -22,7 +22,7 @@ static DataBuffer Inflate(const std::uint8_t* source, std::size_t size, std::siz
|
||||
|
||||
static DataBuffer Deflate(const std::uint8_t* source, std::size_t size) {
|
||||
DataBuffer result;
|
||||
uLongf compressedSize = size;
|
||||
uLongf compressedSize;
|
||||
|
||||
result.Resize(size); // Resize for the compressed data to fit into
|
||||
compress(
|
||||
|
||||
@@ -32,7 +32,7 @@ float EaseOutCubic(float x) {
|
||||
}
|
||||
|
||||
float EaseInOutCubic(float x) {
|
||||
return x < 0.5f ? 4.0f * EaseInCubic(x) : 1.0f - std::pow(-2.0f * x + 2.0f, 3.0f) / 2.0f;
|
||||
return static_cast<float>(x < 0.5 ? 4 * EaseInCubic(x) : 1 - std::pow(-2 * x + 2, 3) / 2.0);
|
||||
}
|
||||
|
||||
/* Quint functions */
|
||||
@@ -60,8 +60,8 @@ float EaseOutCirc(float x) {
|
||||
}
|
||||
|
||||
float EaseInOutCirc(float x) {
|
||||
return x < 0.5f ? (1.0f - std::sqrt(1.0f - std::pow(2.0f * x, 2.0f))) / 2.0f
|
||||
: (std::sqrt(1.0f - std::pow(-2.0f * x + 2.0f, 2.0f)) + 1.0f) / 2.0f;
|
||||
return static_cast<float>(
|
||||
x < 0.5 ? (1 - std::sqrt(1 - std::pow(2 * x, 2))) / 2.0 : (std::sqrt(1 - std::pow(-2 * x + 2, 2)) + 1) / 2.0);
|
||||
}
|
||||
|
||||
/* Elastic functions */
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "blitz/protocol/packets/ChatPacket.h"
|
||||
|
||||
#include "blitz/common/VarInt.h"
|
||||
#include "blitz/maths/Vector.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include <map>
|
||||
@@ -24,7 +23,7 @@ DataBuffer ChatPacket::Serialize(bool packetID) const {
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
|
||||
data << VarInt{m_Message.size()};
|
||||
data << static_cast<std::uint64_t>(m_Message.size());
|
||||
for (const auto& part : m_Message) {
|
||||
data << part.color << part.text;
|
||||
}
|
||||
@@ -32,12 +31,12 @@ DataBuffer ChatPacket::Serialize(bool packetID) const {
|
||||
}
|
||||
|
||||
void ChatPacket::Deserialize(DataBuffer& data) {
|
||||
VarInt partsNumber;
|
||||
std::uint64_t partsNumber;
|
||||
data >> partsNumber;
|
||||
|
||||
m_Message.resize(partsNumber.GetValue());
|
||||
m_Message.resize(partsNumber);
|
||||
|
||||
for (std::size_t i = 0; i < partsNumber.GetValue(); ++i) {
|
||||
for (std::size_t i = 0; i < partsNumber; ++i) {
|
||||
data >> m_Message[i].color >> m_Message[i].text;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,14 +74,12 @@ void Client::Disconnect() {
|
||||
m_Server->Stop();
|
||||
}
|
||||
m_Connexion->CloseConnection();
|
||||
Reset();
|
||||
|
||||
NotifyListeners(&game::ClientListener::OnGameLeave);
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Client::Reset() {
|
||||
utils::LOGD("[Client] Reset !");
|
||||
// Reset server
|
||||
m_Server.reset(nullptr);
|
||||
m_Server = std::make_unique<server::Server>();
|
||||
|
||||
@@ -1,103 +1,38 @@
|
||||
#include "client/audio/AudioManager.h"
|
||||
|
||||
#include "blitz/maths/Maths.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/audio/AudioBuffer.h"
|
||||
#include "client/game/ClientGame.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace audio {
|
||||
|
||||
AudioManager::AudioManager(Client* client) : m_Client(client), m_Player(nullptr) {
|
||||
AudioManager::AudioManager(Client* client) : m_Client(client) {
|
||||
m_Listener.SetPosition({});
|
||||
m_Listener.SetVelocity({});
|
||||
m_Listener.SetGain(1.0f);
|
||||
InitSounds();
|
||||
m_Listener.SetOrientation(blitz::Vec3f{0.0, 0.0, 0.0}, blitz::Vec3f{0.0, 1.0, 0.0});
|
||||
InitMainMenuMusic();
|
||||
m_MenuMusic->Play();
|
||||
m_Client->BindListener(this);
|
||||
}
|
||||
|
||||
void AudioManager::SetGlobalVolume(float volume) {
|
||||
m_Listener.SetGain(volume);
|
||||
}
|
||||
|
||||
void AudioManager::Update() {
|
||||
if (!m_Player)
|
||||
return;
|
||||
|
||||
m_Listener.SetPosition(m_Player->GetPosition());
|
||||
m_Listener.SetOrientation(maths::GetDirectionVectorFromRotation(m_Player->GetYaw(), m_Player->GetPitch()), {0.0f, 1.0f, 0.0f});
|
||||
m_Listener.SetVelocity(m_Player->GetVelocity());
|
||||
}
|
||||
|
||||
AudioSourcePtr AudioManager::InitSourceFromFile(const std::string& fileName) {
|
||||
AudioBufferPtr audioBuffer = InitBufferFromFile(fileName);
|
||||
return InitSourceFromBuffer(audioBuffer);
|
||||
}
|
||||
|
||||
AudioSourcePtr AudioManager::InitSourceFromBuffer(const AudioBufferPtr& buffer) {
|
||||
AudioSourcePtr audioSource = std::make_unique<AudioSource>();
|
||||
audioSource->SetBuffer(buffer);
|
||||
audioSource->SetPosition({});
|
||||
audioSource->SetVelocity({});
|
||||
audioSource->SetPitch(1.0f);
|
||||
audioSource->SetRelative(false);
|
||||
|
||||
return audioSource;
|
||||
}
|
||||
|
||||
AudioBufferPtr AudioManager::InitBufferFromFile(const std::string& fileName) {
|
||||
AudioData audioData = AudioLoader::LoadAudioFile(fileName);
|
||||
return std::make_shared<AudioBuffer>(std::move(audioData));
|
||||
}
|
||||
|
||||
void AudioManager::InitSounds() {
|
||||
m_MenuMusic = InitSourceFromFile("sessionD.wav");
|
||||
void AudioManager::InitMainMenuMusic() {
|
||||
AudioData audioData = AudioLoader::LoadAudioFile("sessionD.wav");
|
||||
AudioBufferPtr audioBuffer = std::make_unique<AudioBuffer>(std::move(audioData));
|
||||
m_MenuMusic = std::make_unique<AudioSource>();
|
||||
m_MenuMusic->SetBuffer(std::move(audioBuffer));
|
||||
m_MenuMusic->SetPosition({});
|
||||
m_MenuMusic->SetVelocity({});
|
||||
m_MenuMusic->SetPitch(1.0f);
|
||||
m_MenuMusic->SetLooping(true);
|
||||
|
||||
m_LaserSound = InitBufferFromFile("laser.wav");
|
||||
}
|
||||
|
||||
void AudioManager::OnGameJoin() {
|
||||
m_MenuMusic->Stop();
|
||||
m_Client->GetGame()->BindListener(this);
|
||||
}
|
||||
|
||||
void AudioManager::OnGameLeave() {
|
||||
m_MenuMusic->Play();
|
||||
m_PlayerSources.clear();
|
||||
m_Player = nullptr;
|
||||
m_Client->GetGame()->UnbindListener(this);
|
||||
}
|
||||
|
||||
void AudioManager::OnClientPlayerJoin() {
|
||||
m_Player = m_Client->GetGame()->GetPlayerById(m_Client->GetPlayerID());
|
||||
}
|
||||
|
||||
void AudioManager::OnPlayerJoin(game::PlayerID player) {
|
||||
m_PlayerSources.insert({player, PlayerSound{InitSourceFromBuffer(m_LaserSound)}});
|
||||
}
|
||||
|
||||
void AudioManager::OnPlayerLeave(game::PlayerID player) {
|
||||
m_PlayerSources.erase(player);
|
||||
}
|
||||
|
||||
void AudioManager::OnPlayerShoot(game::PlayerID playerID, const Vec3f& position, float yaw, float pitch) {
|
||||
auto it = m_PlayerSources.find(playerID);
|
||||
|
||||
if (it == m_PlayerSources.end()) {
|
||||
utils::LOGD("[AudioManager] No sound found for player " + std::to_string(playerID) + " !");
|
||||
return;
|
||||
}
|
||||
|
||||
game::Player* player = m_Client->GetGame()->GetPlayerById(playerID);
|
||||
assert(player);
|
||||
|
||||
Vec3f shootFront = maths::GetDirectionVectorFromRotation(player->GetYaw(), player->GetPitch());
|
||||
|
||||
PlayerSound& playerSounds = it->second;
|
||||
playerSounds.m_Laser->SetPosition(player->GetPosition());
|
||||
playerSounds.m_Laser->SetDirection(shootFront);
|
||||
playerSounds.m_Laser->Play();
|
||||
}
|
||||
|
||||
AudioManager::~AudioManager() {
|
||||
|
||||
@@ -37,13 +37,9 @@ void AudioSource::SetLooping(bool a_Looping) {
|
||||
alSourcei(m_ID, AL_LOOPING, a_Looping);
|
||||
}
|
||||
|
||||
void AudioSource::SetRelative(bool a_Relative) {
|
||||
alSourcei(m_ID, AL_SOURCE_RELATIVE, a_Relative);
|
||||
}
|
||||
|
||||
void AudioSource::SetBuffer(const AudioBufferPtr& a_Buffer) {
|
||||
void AudioSource::SetBuffer(AudioBufferPtr&& a_Buffer) {
|
||||
alSourcei(m_ID, AL_BUFFER, a_Buffer->GetID());
|
||||
m_Buffer = a_Buffer;
|
||||
m_Buffer = std::move(a_Buffer);
|
||||
}
|
||||
|
||||
AudioSource::SourceState AudioSource::GetSourceState() const {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace blitz {
|
||||
|
||||
Display::Display(int width, int height, const std::string& windowName, Client* client, input::InputManager& inputManager) :
|
||||
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)),
|
||||
@@ -28,9 +28,7 @@ Display::Display(int width, int height, const std::string& windowName, Client* c
|
||||
m_ShouldClose(false),
|
||||
m_FullScreen(false),
|
||||
m_Client(client),
|
||||
m_InputManager(inputManager),
|
||||
m_BlitzGui(nullptr),
|
||||
m_PlayerController(m_Client, m_InputManager) {}
|
||||
m_BlitzGui(nullptr) {}
|
||||
|
||||
Display::~Display() {
|
||||
Destroy();
|
||||
@@ -147,7 +145,7 @@ void Display::PollEvents() {
|
||||
}
|
||||
}
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
m_InputManager.ProcessEvent(event);
|
||||
InputManager::ProcessEvent(event);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
@@ -158,8 +156,6 @@ void Display::PollEvents() {
|
||||
}
|
||||
#endif
|
||||
|
||||
m_PlayerController.Update(ImGui::GetIO().DeltaTime);
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
@@ -168,7 +164,7 @@ void Display::PollEvents() {
|
||||
void Display::Update() {
|
||||
// center mouse
|
||||
#ifndef __ANDROID__
|
||||
if (m_InputManager.MouseGrabbed()) {
|
||||
if (InputManager::MouseGrabbed()) {
|
||||
SDL_WarpMouseInWindow(m_Window, GetWindowWidth() / 2, GetWindowHeight() / 2);
|
||||
}
|
||||
#endif
|
||||
@@ -233,7 +229,7 @@ void Display::InitImGui() {
|
||||
#ifndef __ANDROID__
|
||||
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
#endif
|
||||
m_BlitzGui = std::make_unique<gui::BlitzGui>(m_Client, m_InputManager);
|
||||
m_BlitzGui = std::make_unique<gui::BlitzGui>(m_Client);
|
||||
}
|
||||
|
||||
} // namespace blitz
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
#include <vector>
|
||||
|
||||
namespace blitz {
|
||||
namespace input {
|
||||
namespace InputManager {
|
||||
|
||||
std::vector<KeyDownCallback> KeyCallBacks;
|
||||
std::vector<MouseMoveCallback> MouseCallBacks;
|
||||
|
||||
bool MouseInputGrabbed = false;
|
||||
|
||||
static int ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode) {
|
||||
switch (keycode) {
|
||||
@@ -222,15 +227,36 @@ static int ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode) {
|
||||
return ImGuiKey_None;
|
||||
}
|
||||
|
||||
void InputManager::ProcessEvent(SDL_Event& event) const {
|
||||
void BindKeyDownCallback(const KeyDownCallback& callback) {
|
||||
KeyCallBacks.push_back(callback);
|
||||
}
|
||||
|
||||
void BindMouseMoveCallback(const MouseMoveCallback& callback) {
|
||||
MouseCallBacks.push_back(callback);
|
||||
}
|
||||
|
||||
static void CallKeyFunctions(SDL_Keycode key) {
|
||||
int imguiKey = ImGui_ImplSDL2_KeycodeToImGuiKey(key);
|
||||
for (auto callback : KeyCallBacks) {
|
||||
callback(imguiKey);
|
||||
}
|
||||
}
|
||||
|
||||
static void CallMouseFunctions(int xrel, int yrel) {
|
||||
for (auto callback : MouseCallBacks) {
|
||||
callback(xrel, yrel);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessEvent(SDL_Event& event) {
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN: {
|
||||
NotifyListeners(&InputListener::OnKeyDown, ImGui_ImplSDL2_KeycodeToImGuiKey(event.key.keysym.sym));
|
||||
CallKeyFunctions(event.key.keysym.sym);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_MOUSEMOTION: {
|
||||
NotifyListeners(&InputListener::OnMouseMove, event.motion.xrel, event.motion.yrel);
|
||||
CallMouseFunctions(event.motion.xrel, event.motion.yrel);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -239,16 +265,16 @@ void InputManager::ProcessEvent(SDL_Event& event) const {
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::GrabMouse(bool grabInput) {
|
||||
m_MouseInputGrabbed = grabInput;
|
||||
void GrabMouse(bool grabInput) {
|
||||
MouseInputGrabbed = grabInput;
|
||||
#ifndef __ANDROID__
|
||||
SDL_SetRelativeMouseMode(static_cast<SDL_bool>(grabInput));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool InputManager::MouseGrabbed() const {
|
||||
return m_MouseInputGrabbed;
|
||||
bool MouseGrabbed() {
|
||||
return MouseInputGrabbed;
|
||||
}
|
||||
|
||||
} // namespace input
|
||||
} // namespace InputManager
|
||||
} // namespace blitz
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "blitz/game/Player.h"
|
||||
#include "blitz/maths/Maths.h"
|
||||
#include "blitz/maths/Physics.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/config/BlitzConfig.h"
|
||||
@@ -21,45 +20,32 @@ static constexpr float DEFAULT_MAX_FB_SPEED = 10.;
|
||||
static constexpr float DEFAULT_LR_SPEED_SMOOTHING_TIME = 1.0;
|
||||
static constexpr float DEFAULT_FB_SPEED_SMOOTHING_TIME = 1.0;
|
||||
|
||||
PlayerController::PlayerController(Client* client, input::InputManager& inputManager) :
|
||||
PlayerController::PlayerController(Client* client) :
|
||||
m_Player(nullptr),
|
||||
m_Client(client),
|
||||
m_InputManager(inputManager),
|
||||
m_Velocity({}),
|
||||
m_MaxVelocity(DEFAULT_MAX_LR_SPEED, DEFAULT_JUMP_VEL, DEFAULT_MAX_FB_SPEED),
|
||||
m_MaxVelocity(DEFAULT_MAX_LR_SPEED, DEFAULT_MAX_FB_SPEED, DEFAULT_JUMP_VEL),
|
||||
m_OnGround(true) {
|
||||
m_DxSmoother.Current = 0.0f;
|
||||
m_DySmoother.Current = 0.0f;
|
||||
m_DxSmoother.SetSmoothingTime(DEFAULT_LR_SPEED_SMOOTHING_TIME);
|
||||
m_DySmoother.SetSmoothingTime(DEFAULT_FB_SPEED_SMOOTHING_TIME);
|
||||
m_InputManager.BindListener(this);
|
||||
m_Client->BindListener(this);
|
||||
}
|
||||
|
||||
PlayerController::~PlayerController() {
|
||||
m_InputManager.UnbindListener(this);
|
||||
m_Client->UnbindListener(this);
|
||||
InputManager::BindMouseMoveCallback(
|
||||
std::bind(&PlayerController::MouseMotionEvent, this, std::placeholders::_1, std::placeholders::_2));
|
||||
client->BindListener(this);
|
||||
}
|
||||
|
||||
void PlayerController::OnGameConfigUpdate() {
|
||||
UpdateShootTimer(m_Client->GetGame()->GetGameConfig().FiringRate);
|
||||
}
|
||||
|
||||
void PlayerController::OnClientPlayerJoin() {
|
||||
m_Player = m_Client->GetGame()->GetPlayerById(m_Client->GetPlayerID());
|
||||
}
|
||||
|
||||
void PlayerController::OnGameLeave() {
|
||||
m_Player = nullptr;
|
||||
}
|
||||
|
||||
void PlayerController::UpdateShootTimer(int bpm) {
|
||||
m_ShootTimer.SetCooldown(60.0f / static_cast<float>(bpm));
|
||||
m_ShootTimer.Reset();
|
||||
}
|
||||
|
||||
void PlayerController::OnMouseMove(int deltaX, int deltaY) {
|
||||
if (!m_Player || !m_InputManager.MouseGrabbed())
|
||||
void PlayerController::MouseMotionEvent(int deltaX, int deltaY) {
|
||||
if (!m_Player || !InputManager::MouseGrabbed())
|
||||
return;
|
||||
|
||||
float MouseSpeed = m_Client->GetConfig()->GetMouseSpeed();
|
||||
@@ -73,7 +59,7 @@ void PlayerController::Update(float delta) {
|
||||
if (!m_Player)
|
||||
return;
|
||||
|
||||
if (m_InputManager.MouseGrabbed()) {
|
||||
if (InputManager::MouseGrabbed()) {
|
||||
Keybinds keys = m_Client->GetConfig()->GetKeys();
|
||||
float lr = static_cast<float>(ImGui::IsKeyDown((ImGuiKey(keys[kaAvancer])))) -
|
||||
static_cast<float>(ImGui::IsKeyDown((ImGuiKey(keys[kaReculer]))));
|
||||
@@ -81,19 +67,13 @@ void PlayerController::Update(float delta) {
|
||||
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::fmaxf(sqrt(lr * lr + fb * fb), 1.0f);
|
||||
|
||||
static constexpr float AIR_MOVEMENT_DAMP = 3.0f;
|
||||
float no = std::fmaf(static_cast<float>(!m_OnGround), AIR_MOVEMENT_DAMP, 1.0f);
|
||||
|
||||
m_DxSmoother.SetSmoothingTime(DEFAULT_LR_SPEED_SMOOTHING_TIME * no);
|
||||
m_DySmoother.SetSmoothingTime(DEFAULT_FB_SPEED_SMOOTHING_TIME * no);
|
||||
float scale = 1.0f / std::max(sqrt(lr * lr + fb * fb), 1.0f);
|
||||
|
||||
m_Velocity.x = lr * m_MaxVelocity.x * scale;
|
||||
m_Velocity.z = fb * m_MaxVelocity.z * scale;
|
||||
m_Velocity.y = fb * m_MaxVelocity.y * scale;
|
||||
|
||||
if (ImGui::IsKeyDown(ImGuiKey::ImGuiKey_Space) && m_OnGround) {
|
||||
m_Velocity.y = m_MaxVelocity.y;
|
||||
m_Velocity.z = m_MaxVelocity.z;
|
||||
NotifyListeners(&game::PlayerInputListener::OnLocalPlayerJump);
|
||||
}
|
||||
|
||||
@@ -104,22 +84,12 @@ void PlayerController::Update(float delta) {
|
||||
m_ShootTimer.ApplyCooldown();
|
||||
}
|
||||
} else {
|
||||
m_Velocity.x = m_Velocity.z = 0.0f;
|
||||
m_Velocity.x = m_Velocity.y = 0.0f;
|
||||
}
|
||||
|
||||
ApplyGravity(delta);
|
||||
|
||||
UpdatePosition(delta);
|
||||
}
|
||||
|
||||
void PlayerController::ApplyForce(const Vec3f& f, float delta) {
|
||||
m_Velocity += f * delta;
|
||||
}
|
||||
|
||||
void PlayerController::ApplyGravity(float delta) {
|
||||
ApplyForce(Vec3f { 0.0f, -m_Client->GetGame()->GetGameConfig().Gravity, 0.0f }, delta);
|
||||
}
|
||||
|
||||
void PlayerController::UpdatePosition(const float delta) {
|
||||
|
||||
float yaw = m_Player->GetYaw();
|
||||
@@ -127,54 +97,28 @@ void PlayerController::UpdatePosition(const float delta) {
|
||||
float cosine = std::cos(yaw);
|
||||
|
||||
m_DxSmoother.Tick(m_Velocity.x, delta);
|
||||
m_DySmoother.Tick(m_Velocity.z, delta);
|
||||
m_DySmoother.Tick(m_Velocity.y, delta);
|
||||
|
||||
float dx_smooth = m_DxSmoother.Current;
|
||||
float dy_smooth = m_DySmoother.Current;
|
||||
|
||||
Vec3f vel = Vec3f((dx_smooth * cosine + dy_smooth * sine), m_Velocity.y, (dx_smooth * sine - dy_smooth * cosine)) * delta;
|
||||
maths::CollisionData collision { Vec3f::splat(0.0f), vel };
|
||||
float dx = (dx_smooth * cosine + dy_smooth * sine) * delta;
|
||||
float dy = (dx_smooth * sine - dy_smooth * cosine) * delta;
|
||||
|
||||
const auto& aabbs = m_Client->GetGame()->GetWorld()->GetAABBs();
|
||||
maths::AABB hitbox = m_Player->GetHitBox();
|
||||
float dz = m_Velocity.z * delta;
|
||||
|
||||
bool on_ground = false;
|
||||
// the floor here is y-level zero, once downwards collision lands it will be dynmicallly calculated
|
||||
// assumed to be a negative number
|
||||
const float floor_dist = 0.0f - m_Player->GetPosition().y;
|
||||
|
||||
do {
|
||||
|
||||
maths::IntersectionData closest { 1.0f, maths::Axis::aY };
|
||||
|
||||
for (const maths::AABB& aabb : aabbs) {
|
||||
|
||||
auto intersection = hitbox.Intersection(aabb, collision.slide);
|
||||
if (intersection.has_value()) {
|
||||
|
||||
float d = intersection->distance;
|
||||
if (d < closest.distance) {
|
||||
|
||||
maths::Axis axis = intersection->axis;
|
||||
on_ground |= (axis == maths::Axis::aY);
|
||||
|
||||
closest.distance = d;
|
||||
closest.axis = axis;
|
||||
}
|
||||
}
|
||||
if ((m_OnGround = (dz <= floor_dist))) {
|
||||
dz = floor_dist;
|
||||
m_Velocity.z = 0.0f;
|
||||
} else {
|
||||
m_Velocity.z -= m_Client->GetGame()->GetGameConfig().Gravity * 1.0f * delta;
|
||||
}
|
||||
|
||||
if (closest.distance < 0.99f) {
|
||||
m_Velocity[closest.axis] = 0.0f;
|
||||
}
|
||||
|
||||
collision = closest.ToCollision(collision.slide);
|
||||
|
||||
Vec3f v = collision.delta;
|
||||
|
||||
m_Player->AddPosition(v);
|
||||
m_Player->SetVelocity(v);
|
||||
|
||||
} while (maths::Length(collision.slide) > 1e-6);
|
||||
|
||||
m_OnGround = on_ground;
|
||||
m_Player->AddPosition({dx, dz, dy});
|
||||
}
|
||||
|
||||
} // namespace input
|
||||
|
||||
@@ -13,14 +13,12 @@
|
||||
#include "blitz/protocol/packets/UpdateGameStatePacket.h"
|
||||
#include "blitz/protocol/packets/UpdateHealthPacket.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/game/ClientWorld.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace client {
|
||||
|
||||
ClientGame::ClientGame(Client* client, protocol::PacketDispatcher* dispatcher) :
|
||||
protocol::PacketHandler(dispatcher), m_Client(client) {
|
||||
m_World = std::make_unique<ClientWorld>(this);
|
||||
RegisterHandlers();
|
||||
}
|
||||
|
||||
@@ -33,8 +31,8 @@ void ClientGame::AddPlayer(game::PlayerID player, const std::string& name) {
|
||||
m_LeaderBoard.AddPlayer(GetPlayerById(player));
|
||||
}
|
||||
void ClientGame::RemovePlayer(game::PlayerID player) {
|
||||
m_LeaderBoard.RemovePlayer(player);
|
||||
Game::RemovePlayer(player);
|
||||
m_LeaderBoard.RemovePlayer(player);
|
||||
}
|
||||
|
||||
void ClientGame::RegisterHandlers() {
|
||||
@@ -50,17 +48,12 @@ void ClientGame::RegisterHandlers() {
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::PlayerJoinPacket* packet) {
|
||||
|
||||
if (packet->GetPlayerID() == m_Client->GetPlayerID()) {
|
||||
m_Client->NotifyListeners(&game::ClientListener::OnGameJoin);
|
||||
}
|
||||
|
||||
AddPlayer(packet->GetPlayerID(), packet->GetPlayerName());
|
||||
|
||||
// Initialize camera
|
||||
if (packet->GetPlayerID() == m_Client->GetPlayerID()) {
|
||||
m_Client->NotifyListeners(&game::ClientListener::OnSpectatorChange, packet->GetPlayerID());
|
||||
m_Client->NotifyListeners(&game::ClientListener::OnClientPlayerJoin);
|
||||
m_Client->NotifyListeners(&game::ClientListener::OnGameJoin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +87,9 @@ void ClientGame::HandlePacket(const protocol::UpdateHealthPacket* packet) {
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::UpdateGameStatePacket* packet) {
|
||||
Game::UpdateGameState(packet->GetGameState(), packet->GetTimeRemaining());
|
||||
m_GameState = packet->GetGameState();
|
||||
m_GameTimer.SetInterval(packet->GetTimeRemaining());
|
||||
m_GameTimer.Reset();
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::ServerConfigPacket* packet) {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#include "client/game/ClientWorld.h"
|
||||
|
||||
#include "client/game/ClientGame.h"
|
||||
#include "client/render/loader/ModelLoader.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace client {
|
||||
|
||||
ClientWorld::ClientWorld(ClientGame* game) : game::World(game) {
|
||||
LoadAABBs();
|
||||
}
|
||||
|
||||
void ClientWorld::LoadAABBs() {
|
||||
m_AABBs = ModelLoader::LoadModelAABBs("sol.glb");
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace blitz
|
||||
@@ -11,14 +11,14 @@
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
BlitzGui::BlitzGui(Client* client, input::InputManager& inputManager) : GuiWidget(nullptr, client) {
|
||||
BlitzGui::BlitzGui(Client* client) : GuiWidget(nullptr, client) {
|
||||
Enable();
|
||||
AddWidget(std::make_unique<GameChatGui>(this, client, inputManager));
|
||||
AddWidget(std::make_unique<MainMenu>(client, inputManager));
|
||||
AddWidget(std::make_unique<GameChatGui>(this, client));
|
||||
AddWidget(std::make_unique<MainMenu>(client));
|
||||
AddWidget(std::make_unique<CrossHair>(client));
|
||||
AddWidget(std::make_unique<Hud>(this, client));
|
||||
AddWidget(std::make_unique<LeaderBoardGui>(this, client));
|
||||
AddWidget(std::make_unique<ServerGui>(this, client, inputManager));
|
||||
AddWidget(std::make_unique<ServerGui>(this, client));
|
||||
SetCustomTheme();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "blitz/misc/Format.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/display/InputManager.h"
|
||||
#include <cmath>
|
||||
#include <imgui.h>
|
||||
#include <string>
|
||||
@@ -10,9 +11,6 @@
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
CreateGameMenu::CreateGameMenu(GuiWidget* parent, Client* client, input::InputManager& inputManager) :
|
||||
GuiWidget(parent, client), m_InputManager(inputManager) {}
|
||||
|
||||
void CreateGameMenu::Render() {
|
||||
if (!IsEnabled())
|
||||
return;
|
||||
@@ -40,7 +38,7 @@ void CreateGameMenu::Render() {
|
||||
utils::LOGD(utils::Format("[CreateGameMenu] Port saisi : %i", InputPort));
|
||||
|
||||
if (m_Client->CreateGame(InputPort, m_Client->GetConfig()->GetPseudo().data())) {
|
||||
m_InputManager.GrabMouse(true);
|
||||
InputManager::GrabMouse(true);
|
||||
Disable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,11 @@ namespace gui {
|
||||
|
||||
static const float ChatFadeTime = 2.0f;
|
||||
|
||||
GameChatGui::GameChatGui(GuiWidget* parent, Client* client, input::InputManager& inputManager) :
|
||||
GuiWidget(parent, client), m_InputManager(inputManager) {
|
||||
GameChatGui::GameChatGui(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {
|
||||
m_Client->BindListener(this);
|
||||
InputBuf[0] = '\0';
|
||||
}
|
||||
|
||||
GameChatGui::~GameChatGui() {
|
||||
m_Client->UnbindListener(this);
|
||||
}
|
||||
|
||||
void GameChatGui::Draw(const char* title, bool* p_open) {
|
||||
HistoryPos = -1;
|
||||
static float chat_width = 620.0f;
|
||||
@@ -96,11 +91,11 @@ void GameChatGui::Render() {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Enter)) {
|
||||
showCHAT = true;
|
||||
m_FocusRequested = true;
|
||||
m_InputManager.GrabMouse(false);
|
||||
InputManager::GrabMouse(false);
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_Escape) && showCHAT) {
|
||||
showCHAT = false;
|
||||
ImGui::GetIO().ClearInputKeys();
|
||||
m_InputManager.GrabMouse(true);
|
||||
InputManager::GrabMouse(true);
|
||||
}
|
||||
|
||||
if (showCHAT) {
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
JoinGameMenu::JoinGameMenu(GuiWidget* parent, Client* client, input::InputManager& inputManager) :
|
||||
GuiWidget(parent, client), m_InputManager(inputManager) {}
|
||||
|
||||
void JoinGameMenu::Render() {
|
||||
if (!IsEnabled())
|
||||
return;
|
||||
@@ -45,7 +42,7 @@ void JoinGameMenu::Render() {
|
||||
utils::LOGD(utils::Format("[JoinGameMenu] Adresse saisie : %s, Port saisi : %i", InputAddress, InputPort));
|
||||
|
||||
if (m_Client->JoinGame(m_Client->GetConfig()->GetPseudo().data(), InputAddress, InputPort)) {
|
||||
m_InputManager.GrabMouse(true);
|
||||
InputManager::GrabMouse(true);
|
||||
Disable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
#include "client/gui/MainMenu.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "client/gui/CreateGameMenu.h"
|
||||
#include "client/gui/JoinGameMenu.h"
|
||||
#include "client/gui/OptionsMenu.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
MainMenu::MainMenu(Client* client, input::InputManager& inputManager) : GuiWidget(nullptr, client), m_InputManager(inputManager) {
|
||||
MainMenu::MainMenu(Client* client) : GuiWidget(nullptr, client) {
|
||||
Enable();
|
||||
AddWidget(std::make_unique<CreateGameMenu>(this, client, inputManager));
|
||||
AddWidget(std::make_unique<JoinGameMenu>(this, client, inputManager));
|
||||
AddWidget(std::make_unique<OptionsMenu>(this, client, inputManager));
|
||||
m_Client->BindListener(this);
|
||||
}
|
||||
|
||||
MainMenu::~MainMenu() {
|
||||
m_Client->UnbindListener(this);
|
||||
}
|
||||
|
||||
void MainMenu::OnGameLeave() {
|
||||
Enable();
|
||||
m_InputManager.GrabMouse(false);
|
||||
AddWidget(std::make_unique<CreateGameMenu>(this, client));
|
||||
AddWidget(std::make_unique<JoinGameMenu>(this, client));
|
||||
AddWidget(std::make_unique<OptionsMenu>(this, client));
|
||||
}
|
||||
|
||||
void MainMenu::Render() {
|
||||
|
||||
@@ -42,31 +42,6 @@ static std::string GetImGuiKeyName(int key) {
|
||||
|
||||
|
||||
|
||||
OptionsMenu::OptionsMenu(GuiWidget* parent, Client* client, input::InputManager& inputManager) :
|
||||
GuiWidget(parent, client), m_IsKeyPopupOpen(false), m_KeyPopupShouldClose(false), m_InputManager(inputManager) {
|
||||
AddWidget(std::make_unique<FPSMenu>(this, client));
|
||||
|
||||
m_InputManager.BindListener(this);
|
||||
|
||||
m_ShowFPS = m_Client->GetConfig()->IsFPSDisplayEnabled();
|
||||
m_SubWidgets[0]->SetState(m_ShowFPS);
|
||||
|
||||
m_VSync = m_Client->GetConfig()->IsVSyncEnabled();
|
||||
SDL_GL_SetSwapInterval(m_VSync);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
OptionsMenu::~OptionsMenu() {
|
||||
m_InputManager.UnbindListener(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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())) {
|
||||
@@ -115,7 +90,23 @@ void OptionsMenu::HotkeyBindingPopUp() {
|
||||
|
||||
|
||||
|
||||
void OptionsMenu::OnKeyDown(int key) {
|
||||
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));
|
||||
|
||||
m_ShowFPS = m_Client->GetConfig()->IsFPSDisplayEnabled();
|
||||
m_SubWidgets[0]->SetState(m_ShowFPS);
|
||||
|
||||
m_VSync = m_Client->GetConfig()->IsVSyncEnabled();
|
||||
SDL_GL_SetSwapInterval(m_VSync);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void OptionsMenu::OnKeyEvent(int key) {
|
||||
if (!m_IsKeyPopupOpen)
|
||||
return;
|
||||
|
||||
@@ -149,7 +140,7 @@ void OptionsMenu::Render() {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape) && m_Client->IsConnected() && !IsEnabled()) {
|
||||
Enable();
|
||||
ImGui::GetIO().ClearInputKeys(); // releases the Escape key
|
||||
m_InputManager.GrabMouse(false);
|
||||
InputManager::GrabMouse(false);
|
||||
}
|
||||
|
||||
if (!IsEnabled())
|
||||
@@ -212,7 +203,7 @@ void OptionsMenu::Render() {
|
||||
if (ImGui::Button("Retour", buttonSize) || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
Disable();
|
||||
if (m_Client->IsConnected()) {
|
||||
m_InputManager.GrabMouse(true);
|
||||
InputManager::GrabMouse(true);
|
||||
} else {
|
||||
m_Parent->Enable();
|
||||
}
|
||||
@@ -221,6 +212,7 @@ void OptionsMenu::Render() {
|
||||
if (ImGui::Button("Quitter la partie", buttonSize)) {
|
||||
m_Client->Disconnect();
|
||||
Disable();
|
||||
m_Parent->Enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,15 +10,14 @@
|
||||
namespace blitz {
|
||||
namespace gui {
|
||||
|
||||
ServerGui::ServerGui(GuiWidget* parent, Client* client, input::InputManager& inputManager) :
|
||||
GuiWidget(parent, client), m_InputManager(inputManager) {}
|
||||
ServerGui::ServerGui(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {}
|
||||
|
||||
void ServerGui::Render() {
|
||||
if (!m_Client->IsAdmin())
|
||||
return;
|
||||
|
||||
Keybinds keys = m_Client->GetConfig()->GetKeys();
|
||||
if (ImGui::IsKeyPressed(ImGuiKey(keys[kaFenetreAdmin])) && m_InputManager.MouseGrabbed()) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey(keys[kaFenetreAdmin])) && InputManager::MouseGrabbed()) {
|
||||
ImGui::OpenPopup("FENETRE D'ADMIN");
|
||||
}
|
||||
|
||||
@@ -33,7 +32,7 @@ void ServerGui::Render() {
|
||||
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||
ImGui::SetNextWindowSize(ImVec2(servergui_width, servergui_height));
|
||||
if (ImGui::BeginPopupModal("FENETRE D'ADMIN", nullptr, servergui_flags)) {
|
||||
m_InputManager.GrabMouse(false);
|
||||
InputManager::GrabMouse(false);
|
||||
|
||||
ImGui::BeginChild("Mutateurs JOUEURS", ImVec2(servergui_width * (1.0f / 3.0f), 0.0f), true);
|
||||
{
|
||||
@@ -116,7 +115,7 @@ void ServerGui::Render() {
|
||||
ImGui::SetCursorPosY(servergui_height - 2.0f * buttonSize.y);
|
||||
if (ImGui::Button("Retour", buttonSize)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
m_InputManager.GrabMouse(true);
|
||||
InputManager::GrabMouse(true);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@ BulletRenderer::~BulletRenderer() {}
|
||||
void BulletRenderer::AddBullet(const Vec3f& origin, float yaw, float pitch, bool firstPersson) {
|
||||
static const float TRAIL_LENGHT = 50;
|
||||
|
||||
Vec3f direction = maths::GetDirectionVectorFromRotation(yaw, pitch);
|
||||
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);
|
||||
|
||||
@@ -80,9 +84,5 @@ void BulletRenderer::Render() {
|
||||
vao->Unbind();
|
||||
}
|
||||
|
||||
void BulletRenderer::Clear() {
|
||||
m_Trails.clear();
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
} // namespace blitz
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
namespace blitz {
|
||||
namespace render {
|
||||
|
||||
/// \brief Eye height from center
|
||||
static const float EyeHeight = 0.5f;
|
||||
static const float EyeHeight = 1.25f;
|
||||
|
||||
void Camera::Update(float delta) {
|
||||
int windowWidth = static_cast<int>(ImGui::GetIO().DisplaySize.x);
|
||||
@@ -17,12 +16,8 @@ void Camera::Update(float delta) {
|
||||
if (windowWidth != m_LastWindowSize.x || windowHeight != m_LastWindowSize.y) {
|
||||
m_LastWindowSize = {windowWidth, windowHeight};
|
||||
|
||||
m_PerspectiveMatrix = maths::Perspective(
|
||||
80.0f / 180.0f * maths::PI,
|
||||
static_cast<float>(windowHeight) / static_cast<float>(windowWidth),
|
||||
0.1f,
|
||||
160.0f
|
||||
);
|
||||
m_PerspectiveMatrix =
|
||||
maths::Perspective(80.0f / 180.0f * maths::PI, static_cast<float>(windowWidth) / windowHeight, 0.1f, 160.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,11 +26,12 @@ float Camera::GetPlayerEyeHeight() {
|
||||
}
|
||||
|
||||
Mat4f Camera::GetViewMatrix() const {
|
||||
Vec3f front = {
|
||||
std::cos(m_Player->GetYaw()) * std::cos(m_Player->GetPitch()),
|
||||
std::sin(m_Player->GetPitch()),
|
||||
std::sin(m_Player->GetYaw()) * std::cos(m_Player->GetPitch()),
|
||||
};
|
||||
|
||||
if (!m_Player)
|
||||
return {};
|
||||
|
||||
Vec3f front = maths::GetDirectionVectorFromRotation(m_Player->GetYaw(), m_Player->GetPitch());
|
||||
return maths::Look(m_Player->GetPosition() + Vec3f{0, EyeHeight, 0}, front, {0, 1, 0});
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ namespace render {
|
||||
static const Vec4f SkyColor = {0.6f, 0.8f, 1.0f, 1.0f};
|
||||
static const Vec4f MenuColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
MainRenderer::MainRenderer(Client* client, input::PlayerController& playerController) :
|
||||
m_Client(client), m_ShootTime(0), m_BulletRenderer(m_Camera), m_PlayerController(playerController) {
|
||||
MainRenderer::MainRenderer(Client* client) :
|
||||
m_Client(client), m_PlayerController(m_Client), m_ShootTime(0), m_BulletRenderer(m_Camera) {
|
||||
|
||||
LoadModels();
|
||||
|
||||
@@ -54,15 +54,10 @@ MainRenderer::MainRenderer(Client* client, input::PlayerController& playerContro
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
MainRenderer::~MainRenderer() {
|
||||
m_Client->UnbindListener(this);
|
||||
|
||||
m_PlayerController.UnbindListener(this);
|
||||
m_PlayerController.UnbindListener(m_Client);
|
||||
}
|
||||
MainRenderer::~MainRenderer() {}
|
||||
|
||||
void MainRenderer::LoadModels() {
|
||||
m_WorldModel = ModelLoader::LoadModel("sol.glb");
|
||||
m_WorldModel = ModelLoader::LoadModel("base_deambu.glb");
|
||||
m_PlayerModel = ModelLoader::LoadModel("human.obj");
|
||||
m_GunModel = ModelLoader::LoadModel("fingergun.obj");
|
||||
|
||||
@@ -163,6 +158,7 @@ void MainRenderer::Update() {
|
||||
|
||||
float delta = ImGui::GetIO().DeltaTime;
|
||||
|
||||
m_PlayerController.Update(delta);
|
||||
m_Camera.Update(delta);
|
||||
m_BulletRenderer.Update(delta);
|
||||
|
||||
@@ -183,15 +179,11 @@ void MainRenderer::Update() {
|
||||
m_ShootTime = std::max(0.0f, m_ShootTime - delta);
|
||||
}
|
||||
|
||||
void MainRenderer::OnGameLeave() {
|
||||
m_Camera.SetAttachedPlayer(nullptr);
|
||||
m_BulletRenderer.Clear();
|
||||
}
|
||||
|
||||
void MainRenderer::OnSpectatorChange(const game::PlayerID player) {
|
||||
game::Player* playerPtr = m_Client->GetGame()->GetPlayerById(player);
|
||||
|
||||
m_Camera.SetAttachedPlayer(playerPtr);
|
||||
m_PlayerController.SetAttachedPlayer(playerPtr);
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -101,15 +101,14 @@ Model LoadModel(const std::string& fileName) {
|
||||
|
||||
const aiScene* scene = importer.ReadFileFromMemory(fileData.data(), fileData.GetSize(),
|
||||
aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_OptimizeGraph |
|
||||
aiProcess_OptimizeMeshes | aiProcess_GenBoundingBoxes);
|
||||
|
||||
aiProcess_OptimizeMeshes);
|
||||
|
||||
if (nullptr == scene) {
|
||||
utils::LOGE("[ModelLoader] Failed to load model !");
|
||||
return {};
|
||||
}
|
||||
|
||||
utils::LOGD(utils::Format("[ModelLoader]\tModel nodes : %i", scene->mRootNode->mNumChildren));
|
||||
utils::LOGD(utils::Format("[ModelLoader]\tModel nodes : %i", scene->mRootNode->mNumMeshes));
|
||||
|
||||
Model model;
|
||||
ProcessNode(scene->mRootNode, scene, model.mVaos, {});
|
||||
@@ -117,47 +116,5 @@ Model LoadModel(const std::string& fileName) {
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void ProcessAABBNode(aiNode* node, const aiScene* scene, std::vector<maths::AABB>& aabbs, const aiMatrix4x4& transform) {
|
||||
// recursive
|
||||
for (unsigned int i = 0; i < node->mNumChildren; i++) {
|
||||
ProcessAABBNode(node->mChildren[i], scene, aabbs, transform * node->mTransformation);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
aiAABB& aabb = mesh->mAABB;
|
||||
|
||||
aiVector3D aabbMin = transform * node->mTransformation * aabb.mMin;
|
||||
aiVector3D aabbMax = transform * node->mTransformation * aabb.mMax;
|
||||
|
||||
aabbs.push_back({Vec3f{aabbMin.x, aabbMin.y, aabbMin.z}, {aabbMax.x, aabbMax.y, aabbMax.z}});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<maths::AABB> LoadModelAABBs(const std::string& fileName) {
|
||||
DataBuffer fileData = utils::AssetsManager::GetAsset(fileName);
|
||||
|
||||
Assimp::Importer importer;
|
||||
|
||||
const aiScene* scene = importer.ReadFileFromMemory(fileData.data(), fileData.GetSize(), aiProcess_GenBoundingBoxes);
|
||||
|
||||
if (nullptr == scene) {
|
||||
utils::LOGE("[ModelLoader] Failed to load AABB model !");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<maths::AABB> aabbs;
|
||||
ProcessAABBNode(scene->mRootNode, scene, aabbs, {});
|
||||
|
||||
utils::LOGD(utils::Format("[ModelLoader]\tAABB count : %i", aabbs.size()));
|
||||
|
||||
return aabbs;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ModelLoader
|
||||
} // namespace blitz
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
|
||||
Server::Server() : m_TickCounter(SERVER_TPS), m_Game(this), m_ServerRunning(false), m_FreePlayerID(0) {}
|
||||
Server::Server() : m_TickCounter(SERVER_TPS), m_Game(this), m_ServerRunning(false) {}
|
||||
|
||||
Server::~Server() {
|
||||
StopThread();
|
||||
@@ -112,8 +112,10 @@ void Server::Accept() {
|
||||
}
|
||||
|
||||
game::PlayerID Server::GetNewPlayerID() {
|
||||
m_FreePlayerID++;
|
||||
return m_FreePlayerID - 1;
|
||||
static game::PlayerID lastPlayerID = 0;
|
||||
game::PlayerID newPlayerID = lastPlayerID;
|
||||
lastPlayerID++;
|
||||
return newPlayerID;
|
||||
}
|
||||
|
||||
void Server::UpdateSockets() {
|
||||
@@ -182,7 +184,11 @@ void Server::KickPlayer(game::PlayerID playerID) {
|
||||
return;
|
||||
|
||||
m_Game.RemovePlayer(playerID);
|
||||
|
||||
if (player->IsBot()) {
|
||||
} else {
|
||||
RemoveConnexion(playerID);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -20,23 +20,17 @@ namespace server {
|
||||
|
||||
ServerGame::ServerGame(Server* server) : m_Server(server), m_PositionTimer(SERVER_TPS) {
|
||||
CancelGame();
|
||||
InitGameConfig();
|
||||
}
|
||||
|
||||
ServerGame::~ServerGame() {}
|
||||
|
||||
void ServerGame::StartGame() {
|
||||
UpdateGameState(game::gsPreparing, m_ServerDuration.m_PrepDuration);
|
||||
SetGameState(game::gsPreparing, m_ServerDuration.m_PrepDuration);
|
||||
m_Server->BroadcastChatMessage(protocol::ChatPacket::GetTextColor(protocol::AQUA) + "La partie commence dans 10s !");
|
||||
}
|
||||
|
||||
void ServerGame::CancelGame() {
|
||||
UpdateGameState(game::gsWaiting, 0);
|
||||
}
|
||||
|
||||
void ServerGame::InitGameConfig() {
|
||||
m_Config.FiringRate = 120;
|
||||
m_Config.Gravity = 20.0f;
|
||||
SetGameState(game::gsWaiting, 0);
|
||||
}
|
||||
|
||||
void ServerGame::Tick(std::uint64_t delta) {
|
||||
@@ -47,18 +41,18 @@ void ServerGame::Tick(std::uint64_t delta) {
|
||||
if (m_GameState != game::gsWaiting && m_GameTimer.Update(delta)) {
|
||||
switch (m_GameState) {
|
||||
case game::gsPreparing:
|
||||
UpdateGameState(game::gsGame, m_ServerDuration.m_GameDuration);
|
||||
SetGameState(game::gsGame, m_ServerDuration.m_GameDuration);
|
||||
break;
|
||||
|
||||
case game::gsGame:
|
||||
UpdateGameState(game::gsEnd, m_ServerDuration.m_EndDuration);
|
||||
SetGameState(game::gsEnd, m_ServerDuration.m_EndDuration);
|
||||
break;
|
||||
|
||||
case game::gsEnd: {
|
||||
if (m_Players.size() > 1) {
|
||||
UpdateGameState(game::gsGame, m_ServerDuration.m_GameDuration);
|
||||
SetGameState(game::gsGame, m_ServerDuration.m_GameDuration);
|
||||
} else {
|
||||
UpdateGameState(game::gsWaiting, 0);
|
||||
SetGameState(game::gsWaiting, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -78,13 +72,15 @@ void ServerGame::SendPlayerPositions() {
|
||||
|
||||
void ServerGame::ProcessShoot(game::PlayerID shooter, Vec3f position, float yaw, float pitch) {
|
||||
maths::Ray shootRay;
|
||||
shootRay.origin = position + Vec3f{0.0, 0.85, 0.0};
|
||||
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);
|
||||
@@ -92,7 +88,7 @@ void ServerGame::ProcessShoot(game::PlayerID shooter, Vec3f position, float yaw,
|
||||
shooterPlayer->GetStats().m_ShootCount++;
|
||||
|
||||
for (auto& [playerId, player] : GetPlayers()) {
|
||||
if (playerId != shooter && shootRay.Intersects(player.GetHitBox())) {
|
||||
if (playerId != shooter && maths::Intersects(shootRay, playerStaticAABB + player.GetPosition())) {
|
||||
if (!shootLanded) {
|
||||
shootLanded = true;
|
||||
shooterPlayer->GetStats().m_ShootSuccessCount++;
|
||||
@@ -183,8 +179,10 @@ void ServerGame::ResetPlayerStats() {
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::UpdateGameState(game::GameState gameState, std::uint64_t duration) {
|
||||
Game::UpdateGameState(gameState, duration);
|
||||
void ServerGame::SetGameState(game::GameState gameState, std::uint64_t duration) {
|
||||
m_GameState = gameState;
|
||||
m_GameTimer.SetInterval(duration);
|
||||
m_GameTimer.Reset();
|
||||
|
||||
if (gameState == game::gsGame) {
|
||||
ResetPlayerStats();
|
||||
|
||||
70
test/test_intersects.cpp
Normal file → Executable file
70
test/test_intersects.cpp
Normal file → Executable file
@@ -1,11 +1,11 @@
|
||||
#include "blitz/misc/Test.h"
|
||||
|
||||
#include "blitz/maths/Physics.h"
|
||||
#include "blitz/misc/Format.h"
|
||||
#include "blitz/misc/Log.h"
|
||||
#include "blitz/misc/Format.h"
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
#include <limits>
|
||||
|
||||
using namespace blitz;
|
||||
using namespace maths;
|
||||
@@ -13,80 +13,80 @@ 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}};
|
||||
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(ray.Intersects(box));
|
||||
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}};
|
||||
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(ray.Intersects(box));
|
||||
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}};
|
||||
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(ray.Intersects(box));
|
||||
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}};
|
||||
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(ray.Intersects(box));
|
||||
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}};
|
||||
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(ray.Intersects(box));
|
||||
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}};
|
||||
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(ray.Intersects(box));
|
||||
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}};
|
||||
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(!ray.Intersects(box));
|
||||
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}};
|
||||
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(ray.Intersects(box));
|
||||
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}};
|
||||
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(ray.Intersects(box));
|
||||
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}};
|
||||
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(ray.Intersects(box));
|
||||
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}};
|
||||
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(ray.Intersects(box));
|
||||
blitz_test_assert(Intersects(ray, box));
|
||||
}
|
||||
|
||||
int main(int argc, const char* args[]) {
|
||||
|
||||
Reference in New Issue
Block a user