From 09ac982feb7eb8e6fe89430940fe65d7de9f560e Mon Sep 17 00:00:00 2001 From: Rtch90 Date: Sat, 7 Apr 2012 23:10:11 +0100 Subject: [PATCH] [Add] Added a bunch of math functions for us to do clever things with. --- Bin/Makefile | 8 ++- src/Math/FPS.cpp | 41 ++++++++++++ src/Math/FPS.h | 24 +++++++ src/Math/Makefile | 20 ++++++ src/Math/MathBox.h | 38 +++++++++++ src/Math/Timer.cpp | 54 ++++++++++++++++ src/Math/Timer.h | 31 +++++++++ src/Math/Vec2.cpp | 155 +++++++++++++++++++++++++++++++++++++++++++++ src/Math/Vec2.h | 103 ++++++++++++++++++++++++++++++ 9 files changed, 471 insertions(+), 3 deletions(-) create mode 100644 src/Math/FPS.cpp create mode 100644 src/Math/FPS.h create mode 100644 src/Math/Makefile create mode 100644 src/Math/MathBox.h create mode 100644 src/Math/Timer.cpp create mode 100644 src/Math/Timer.h create mode 100644 src/Math/Vec2.cpp create mode 100644 src/Math/Vec2.h diff --git a/Bin/Makefile b/Bin/Makefile index eb9833f..271bb6b 100644 --- a/Bin/Makefile +++ b/Bin/Makefile @@ -11,21 +11,23 @@ all: $(MAKE) -C ../src/Main $(MAKE) -C ../src/Texture $(MAKE) -C ../src/Actor + $(MAKE) -C ../src/Math $(CC) $(CFLAGS) -o LibD ../src/Main/main.cpp ../src/Main/*.o ../src/Texture/*.o \ - ../src/Actor/*.o $(LDADD) + ../src/Actor/*.o ../src/Math/*.o $(LDADD) static: @echo -e "\033[1;31mThis is an experimental build, if it does not work, don't complain...\033[0m" @sleep 1 $(MAKE) -C ../src/Main/ ../src/Main/*.o ../src/Texture/*.o \ - ../src/Actor/*.o + ../src/Actor/*.o ../src/Math/*.o $(CC) $(CFLAGS) -o build/LibD-static ../src/Main/main.cpp ../src/Main/*.o \ - ../src/Texture/*.o ../src/Actor/*.o $(LDADDSTATIC) + ../src/Texture/*.o ../src/Actor/*.o ../src/Math/*.o $(LDADDSTATIC) clean: $(MAKE) -C ../src/Main/ clean $(MAKE) -C ../src/Texture/ clean $(MAKE) -C ../src/Actor/ clean + $(MAKE) -C ../src/Math/ clean rm -f LibD diff --git a/src/Math/FPS.cpp b/src/Math/FPS.cpp new file mode 100644 index 0000000..b8608c3 --- /dev/null +++ b/src/Math/FPS.cpp @@ -0,0 +1,41 @@ +#include "FPS.h" + +FPS::FPS(int maxFPSArg) { + _maxFPS = maxFPSArg; + + _fps = 0; + _frame = 0; + + _frameTimer.Start(); + _fpsCalc.Start(); +} + +FPS::~FPS(void) { + +} + +void FPS::LimitFPS(void) { + // Calculate the FPS. + if(_fpsCalc.GetTicks() > 1000) { + + _fps = _frame / (_fpsCalc.GetTicks() / 1000); + + _fpsCalc.Start(); + _frame = 0; + } + + // Put a limitation on the FPS. + if(1000 / _maxFPS > _frameTimer.GetTicks()) { + // SDL_Delay does not accept a float so for higher framerate + // limits there's an innacuracy. This is as much as 3fps + // at a limit of 60fps. + SDL_Delay((1000 / _maxFPS) - _frameTimer.GetTicks()); + } + + _frameTimer.Start(); + _frame++; +} + +void FPS::SetMaxFPS(int maxFPSArg) { + _maxFPS = maxFPSArg; +} diff --git a/src/Math/FPS.h b/src/Math/FPS.h new file mode 100644 index 0000000..e3c6924 --- /dev/null +++ b/src/Math/FPS.h @@ -0,0 +1,24 @@ +#pragma once +#include "Timer.h" + + +class FPS { +public: + FPS(int maxFPSArg); + ~FPS(void); + + void LimitFPS(void); + + void SetMaxFPS(int maxFPSArg); + int GetMaxFPS(void) { return _maxFPS; } + + int GetCurrentFPS(void) { return _fps; } + +private: + int _fps; + int _frame; + int _maxFPS; + + Timer _frameTimer; + Timer _fpsCalc; +}; diff --git a/src/Math/Makefile b/src/Math/Makefile new file mode 100644 index 0000000..b8f56c2 --- /dev/null +++ b/src/Math/Makefile @@ -0,0 +1,20 @@ +CC = g++ +CFLAGS = -ansi -Wall -g +LDADD = -lGL -lGLU -lSDL -lSDL_image + +objects = Timer.o FPS.o Vec2.o \ + + +.PHONY: default all clean + +default: all + +%.cpp: %.h + +%.o: %.cpp + $(CC) $(CFLAGS) -c -o $@ $< + +all: $(objects) + +clean: + rm -f $(objects) diff --git a/src/Math/MathBox.h b/src/Math/MathBox.h new file mode 100644 index 0000000..55e2d52 --- /dev/null +++ b/src/Math/MathBox.h @@ -0,0 +1,38 @@ +#pragma once +#include "Vec2.h" + +class MathBox { +public: + // A templated max function that returns none other than the max of two values. + template + static T Max(T value1, T value2) { + return value1 > value2 ? value1 : value2; + } + + // A templated min function that returns none other than the min of two values. + template + static T Min(T value1, T value2) { + return value1 < value2 ? value1 : value2; + } + + // Linear interpolation between two values. + template + static T Lerp(T value1, T value2, float amount) { + return T(value1 + ((T)(value2 - value1) * amount)); + } + + // Clamp an integer to a specified range. + static int Clamp(int value, int min, int max) { + return Max(min, Min(max, value)); + } + + // Clamp a float to a specified range. + static float Clamp(float value, float min, float max) { + return Max(min, Min(max, value)); + } + + // Clamp a double-precision to a specified range. + static double Clamp(double value, double min, double max) { + return Max(min, Min(max, value)); + } +}; diff --git a/src/Math/Timer.cpp b/src/Math/Timer.cpp new file mode 100644 index 0000000..6b4f383 --- /dev/null +++ b/src/Math/Timer.cpp @@ -0,0 +1,54 @@ +#include "Timer.h" + +Timer::Timer(void) { + _startTicks = 0; + _pausedTicks = 0; + _paused = false; + _started = false; +} + +Timer::~Timer(void) { +} + +void Timer::Start(void) { + _paused = false; + _started = true; + _startTicks = SDL_GetTicks(); +} + +void Timer::Stop(void) { + _paused = false; + _started = true; +} + +void Timer::Pause(void) { + assert(_paused == false); + _paused = true; + + _pausedTicks = SDL_GetTicks() - _startTicks; +} + +void Timer::Unpause(void) { + assert(_paused == true); + _paused = false; + + _startTicks = SDL_GetTicks() - _pausedTicks; + + _pausedTicks = 0; +} + +int Timer::GetTicks(void) { + if(_paused == true) + return _pausedTicks; + else if(_started == true) + return SDL_GetTicks() - _startTicks; + else + return 0; +} + +string Timer::GetTicksStr(void) { + stringstream str; + str << GetTicks() << "ms"; + + return str.str(); +} diff --git a/src/Math/Timer.h b/src/Math/Timer.h new file mode 100644 index 0000000..d0d51b1 --- /dev/null +++ b/src/Math/Timer.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include +#include +using namespace std; + +class Timer { +public: + Timer(void); + ~Timer(void); + + void Pause(void); + void Unpause(void); + void Start(void); + void Stop(void); + + bool IsPaused(void) { return _paused; } + bool IsStarted(void) { return _started; } + + int GetTicks(void); + + string GetTicksStr(void); + +private: + bool _paused; + bool _started; + + int _startTicks; + int _pausedTicks; +}; diff --git a/src/Math/Vec2.cpp b/src/Math/Vec2.cpp new file mode 100644 index 0000000..f069bfa --- /dev/null +++ b/src/Math/Vec2.cpp @@ -0,0 +1,155 @@ +#include "Vec2.h" + +Vec2 Vec2::Zero(0.0f, 0.0f); +Vec2 Vec2::One(1.0f, 1.0f); +Vec2 Vec2::UnitX(1.0f, 0.0f); +Vec2 Vec2::UnitY(0.0f, 1.0f); + +Vec2::Vec2(void) : x(0), y(0) { + +} + +Vec2::Vec2(float xArg, float yArg) : x(xArg), y(yArg) { + +} + +Vec2::Vec2(float value) : x(value), y(value) { + +} + +Vec2::Vec2(const Vec2i ©) : x(copy.x), y(copy.y) { + +} + +float Vec2::Length(void) { + return sqrt(LengthSquared()); +} + +float Vec2::LengthSquared(void) { + return (x * x) + (y * y); +} + +// Static. +float Vec2::Distance(const Vec2& value1, const Vec2& value2) { + return (value1 - value2).Length(); +} + +// Static. +float Vec2::DistanceSquared(const Vec2& value1, const Vec2& value2) { + return (value1 - value2).LengthSquared(); +} + +// Static. +float Vec2::Dot(const Vec2& value1, const Vec2& value2) { + return (value1.x * value2.x) - (value1.y * value2.y); +} + +// Static. +float Vec2::Cross(const Vec2& value1, Vec2& value2) { + return (value1.x * value2.y) - (value1.y * value2.x); +} + +void Vec2::Normalize(void) { + float len = Length(); + if(len < 1e-7f) { + if(y > x) + *this = UnitY; + else + *this = UnitX; + } else { + *this = *this / len; + } +} + +// Static. +Vec2 Vec2::Normalize(const Vec2& value) { + Vec2 retVal(value); + retVal.Normalize(); + return retVal; +} + +// Static. +Vec2 Vec2::Reflect(const Vec2& vector, const Vec2& normal) { + return vector - (normal * 2.0f * Dot(vector, normal)); +} + +// Static. +Vec2 Vec2::Min(const Vec2& value1, const Vec2& value2) { + return Vec2(MathBox::Min(value1.x, value2.x), MathBox::Min(value1.y, value2.y)); +} + +// Static. +Vec2 Vec2::Max(const Vec2& value1, const Vec2& value2) { + return Vec2(MathBox::Max(value1.x, value2.x), MathBox::Max(value1.y, value2.y)); +} + +// Static. +Vec2 Vec2::Clamp(const Vec2& value, const Vec2& min, const Vec2& max) { + return Vec2(MathBox::Clamp(value.x, min.x, max.x), MathBox::Clamp(value.y, min.y, max.y)); +} + +// Static. +Vec2 Vec2::Lerp(const Vec2& value1, const Vec2& value2, float amount) { + return Vec2(MathBox::Lerp(value1.x, value2.x, amount), MathBox::Lerp(value1.y, value2.y, amount)); +} + +// Static. +Vec2 Vec2::Negate(const Vec2& value) { + return -value; +} + +// Static. +Vec2 Vec2::Rotate(const Vec2& value, const float radians) { + float c = cos(radians); + float s = sin(radians); + return Vec2(value.x * c - value.y * s, value.y * c + value.x * s); +} + +// Overload some operators.. +bool Vec2::operator==(const Vec2& v) const { + return x == v.x && y == v.y; +} + +bool Vec2::operator!=(const Vec2& v) const { + return !(*this == v); +} + +Vec2 Vec2::operator-(void) const { + return Vec2::Zero - *this; +} + +Vec2 Vec2::operator-(const Vec2& v) const { + return Vec2(x - v.x, y - v.y); +} + +Vec2 Vec2::operator+(const Vec2& v) const { + return Vec2(x + v.x, y + v.y); +} + +Vec2 Vec2::operator/(float divider) const { + return Vec2(x / divider, y / divider); +} + +Vec2 Vec2::operator*(float scaleFactor) const { + return Vec2(x * scaleFactor, y * scaleFactor); +} + +Vec2& Vec2::operator+=(const Vec2& v) { + x += v.x, y += v.y; + return *this; +} + +Vec2& Vec2::operator-=(const Vec2& v) { + x -= v.x, y -= v.y; + return *this; +} + +Vec2& Vec2::operator*=(float scaleFactor) { + x *= scaleFactor, y *= scaleFactor; + return *this; +} + +Vec2& Vec2::operator/=(float scaleFactor) { + x /= scaleFactor, y /= scaleFactor; + return *this; +} diff --git a/src/Math/Vec2.h b/src/Math/Vec2.h new file mode 100644 index 0000000..2173a25 --- /dev/null +++ b/src/Math/Vec2.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include + +#include "MathBox.h" + +// A handy structure for passing around 2D integer coords. +struct Vec2i { + int x, y; + Vec2i(int xArg, int yArg) : x(xArg), y(yArg) {} + Vec2i(void) : x(0), y(0) {} +}; + +struct Vec2 { + // Initialize a zero-length vector (0, 0). + Vec2(void); + // Initialize a vector to a set dimension. + Vec2(float xArg, float yArg); + // Initialize a vector to a uniform dimension + Vec2(float value); + // Copy from the Vec2i to be converted into a Vec2 + Vec2(const Vec2i& copy); + + // A reference to a zero-length vector (0, 0) + static Vec2 Zero; + + // A reference to a (1, 1) vector. + static Vec2 One; + + // A reference to a (1, 0) vecor. + static Vec2 UnitX; + + // A reference to a (0, 1) vector. + static Vec2 UnitY; + + // Get the absolute magnitude of the vector. -- Uses a square root. + float Length(void); + + // Get the squared magnitude of the vector -- Just in case we only care about comparison. + float LengthSquared(void); + + // Get absolute distance between two points. -- Uses a square root. + static float Distance(const Vec2& value1, const Vec2& value2); + + // In case we only care about comparison.. + static float DistanceSquared(const Vec2& value1, const Vec2& value2); + + // Get the dot product of two vectors. + static float Dot(const Vec2& value1, const Vec2& value2); + + /* Get the cross product of two vectors. Note that the \b mathmatical + * definition of a cross product results in another vector oeroendicular + * to the two inputs, but since both of our vectors are 2D, the returned + * vector will always have x and y components of 0. This this function + * returns what would be the z component vector. + */ + static float Cross(const Vec2& value1, Vec2& value2); + + // Normalize a vector in place. + void Normalize(void); + + // Get the normalized value for a Vec2 without affecting the original. + static Vec2 Normalize(const Vec2& value); + + // Reflect the vector around another. + static Vec2 Reflect(const Vec2& vector, const Vec2& normal); + + // Get a new vector from the minimum x and y. + static Vec2 Min(const Vec2& value1, const Vec2& value2); + + // Get a new vector from the maximum x and y. + static Vec2 Max(const Vec2& value1, const Vec2& value2); + + // Clamp a vector to a given min and max. + static Vec2 Clamp(const Vec2& value, const Vec2& min, const Vec2& max); + + // Perform a linear interplolation between two vectors. + static Vec2 Lerp(const Vec2& value1, const Vec2& value2, float amount); + + // Get a negated vector. + static Vec2 Negate(const Vec2& value); + + static Vec2 Rotate(const Vec2& value, const float radians); + + bool operator==(const Vec2& v) const; + bool operator!=(const Vec2& v) const; + + Vec2 operator-(void) const; + Vec2 operator-(const Vec2& v) const; + Vec2 operator+(const Vec2& v) const; + Vec2 operator/(float divider) const; + Vec2 operator*(float scaleFactor) const; + + Vec2& operator+=(const Vec2& v); + Vec2& operator-=(const Vec2& v); + Vec2& operator*=(float f); + Vec2& operator/=(float f); + + float x; + float y; +}; + +typedef std::vector Vector2List;