Ok... I'll post code... but because I use classes it may not be what we are expecting... I've trimmed off includes, inclusion guard statements etc... Also just to mention I use a commentable #define to force my PC build to use the fixed point.
Fixed.h
CODE
class Fixed
{
public:
// Constructors
Fixed(const Fixed &fixNum)
{
fixedNum = fixNum.fixedNum;
scaler = fixNum.scaler;
}
Fixed(const Fixed *fixNum)
{
fixedNum = fixNum->fixedNum;
scaler = fixNum->fixedNum;
}
Fixed() // Creates a default precision Fixed number
{
fixedNum = 0;
scaler = 8;
}
Fixed(int scaler) // Creates a fixed number with the set precision
{
// Scaler is the number of bits for the decimal part
this->scaler = scaler;
fixedNum = 0;
}
~Fixed(){};
void setScaler(int scaler)
{
this->scaler = scaler;
}
//const Fixed& operator= ( const Fixed& fixVal);
//const Fixed& operator= ( const float& val);
// DIVISION
Fixed div(Fixed b);
//Fixed operator%(Fixed b);
Fixed operator/(Fixed b);
// MULTIPLICATION
Fixed mul(Fixed b);
Fixed operator*(Fixed b);
// ADDITION
Fixed add(Fixed b);
Fixed operator+(Fixed b);
// SUBTRACTION
Fixed sub(Fixed b);
Fixed operator-(Fixed b);
//CONSOLE INPUT/OUPUT
void assign(int val)
{
intToFixed(val);
}
void assign(float val)
{
floatToFixed(val);
}
void assign(Fixed val)
{
fixedNum = val.getValue();
scaler = val.getScaler();
}
uint32_t getValue()
{
return fixedNum;
}
int getScaler()
{
return scaler;
}
void floatToFixed(float val);
void intToFixed(int val);
float fixedToFloat();
int fixedToInt();
uint32_t unsign(uint32_t* a)
{
if (*a >= 0)
return 0;
*a = -*a;
return 1;
}
private:
uint32_t fixedNum;// Stores our fixed point number
int scaler; // The precision of the fixed num
};
Fixed.cpp
CODE
// Type conversion
void Fixed::intToFixed(int val)
{
val <<= scaler;
fixedNum = val;
}
int Fixed::fixedToInt()
{
return fixedNum >>= scaler;
}
void Fixed::floatToFixed(float val)
{
uint32_t temp = 1;
temp <<= scaler;
fixedNum = (uint32_t)(val * temp);
}
float Fixed::fixedToFloat()
{
uint32_t temp = 1;
temp <<= scaler;
return ((float)fixedNum/(float)temp);
}
// MULTIPLICATION
Fixed Fixed::mul(Fixed b)
{
uint32_t af=fixedNum&0xFF, bf=b.fixedNum&0xFF;
fixedNum >>= scaler;
b.fixedNum >>= scaler;
Fixed output(scaler);
output.fixedNum = (fixedNum*bf + b.fixedNum*af + (af*bf>>scaler));
output.fixedNum += fixedNum*b.fixedNum<<scaler;
return output;
}
Fixed Fixed:
perator *(Fixed b)
{
return mul(b);
}
// DIVISION
Fixed Fixed::div(Fixed b)
{
Fixed r(scaler);
int s = scaler;
int as = unsign(&fixedNum), bs = unsign(&b.fixedNum), rs = as ^ bs; //needed for sign support only
//if (b == 0) return 0;
while (b.fixedNum < fixedNum)
{
b.fixedNum <<= 1;
s++;
}
int hexScaler = 0x40 << (32-scaler);
while (!(b.fixedNum & hexScaler))
{
fixedNum <<= 1;
b.fixedNum <<= 1;
}
while (fixedNum!=0 && s>=0)
{
if (fixedNum >= b.fixedNum)
{
fixedNum -= b.fixedNum;
r.fixedNum += (1 << s);
}
else
{
b.fixedNum >>= 1;
s--;
}
}
if (rs!=0)
r.fixedNum = -r.fixedNum;
return r;
}
Fixed Fixed:
perator/(Fixed b)
{
return div(b);
}
// ADDITION
Fixed Fixed::add(Fixed b)
{
Fixed output(scaler);
output.fixedNum = fixedNum + b.fixedNum;
return output;
}
Fixed Fixed:
perator+(Fixed b)
{
return add(b);
}
// SUBTRACTION
Fixed Fixed::sub(Fixed b)
{
Fixed output(scaler);
output.fixedNum = fixedNum - b.fixedNum;
return output;
}
Fixed Fixed:
perator-(Fixed b)
{
return sub(b);
}
Timer.h
CODE
class Timer
{
public:
Timer()
{
time = 0;
stored = 0;
lastUpdate = SDL_GetTicks();
mode = SIXTY_FRAMES;
#ifdef PLATFORM_PC
scaler = 0.0f;
#endif
#ifdef PLATFORM_GP2X
scaler.setScaler(8);
scaler.floatToFixed(0.0f);
#endif
}
Timer(int lim)
{
time = lim;
stored = 0;
lastUpdate = SDL_GetTicks();
mode = SIXTY_FRAMES;
#ifdef PLATFORM_PC
scaler = 0.0f;
#endif
#ifdef PLATFORM_GP2X
scaler.setScaler(8);
scaler.floatToFixed(0.0f);
#endif
}
~Timer(){};
void setLimit(int timeLimit) // Set countdown limit
{
time = timeLimit;
}
void setMode(uint mode) // Set the timer scaler
{
this->mode = mode;
calcScaler();
}
void incLimit(int changeOfLimit)// Change the current timelimit
{
time += changeOfLimit;
}
void storeTime() // Store the current time
{
stored = time;
}
int getDifference() // Return the difference between stored time and current time
{
return stored - time;
}
int getRemaining() // Return the remaining coutdown time
{
return time;
}
void update() // progress the timer.
{
#ifdef PLATFORM_GP2X
Fixed temp(8);
temp.assign((int)(SDL_GetTicks() - lastUpdate));
if(temp.getValue() > scaler.getValue()) //one unit has passed
#endif
#ifdef PLATFORM_PC
if(SDL_GetTicks() - lastUpdate > scaler) //one unit has passed
#endif
{
lastUpdate = SDL_GetTicks();
time--;
//cout << "Timer: " << time << endl;
}
}
private:
void calcScaler(); // Calculate the resolution of timer updates
uint mode;
int time;
int stored;
int lastUpdate;
#ifdef PLATFORM_GP2X
Fixed scaler;
#endif
#ifdef PLATFORM_PC
float scaler;
#endif
};
Timer.cpp
CODE
void Timer::calcScaler()
{
#ifdef PLATFORM_PC
scaler = 0.0f;
if (mode == FIFTEEN_FRAMES)
{
scaler = (float)CLOCKS_PER_SEC / 15.0f;
}
else if (mode == THIRTY_FRAMES)
{
scaler = (float)CLOCKS_PER_SEC / 30.0f;
}
else if (mode == FIFTY_FRAMES)
{
scaler = (float)CLOCKS_PER_SEC / 50.0f;
}
else if (mode == SIXTY_FRAMES)
{
scaler = (float)CLOCKS_PER_SEC / 60.0f;
}
else if (mode == NANO_SECONDS)
{
scaler = CLOCKS_PER_SEC / 1000000000;
}
else if (mode == MICRO_SECONDS)
{
scaler = CLOCKS_PER_SEC / 1000000;
}
else if (mode == MILLI_SECONDS)
{
scaler = CLOCKS_PER_SEC / 1000;
}
else if (mode == CENTI_SECONDS)
{
scaler = CLOCKS_PER_SEC / 100;
}
else if (mode == DECI_SECONDS)
{
scaler = CLOCKS_PER_SEC / 10;
}
else if (mode == SECONDS)
{
scaler = CLOCKS_PER_SEC;
}
else if (mode == MINUTES)
{
scaler = CLOCKS_PER_SEC * 60;
}
else if (mode == HOURS)
{
scaler = CLOCKS_PER_SEC * 60 * 60;
}
#endif
#ifdef PLATFORM_GP2X
scaler.assign(0.0f);
if (mode == FIFTEEN_FRAMES)
{
scaler.floatToFixed((float)CLOCKS_PER_SEC / 15.0f);
}
else if (mode == THIRTY_FRAMES)
{
scaler.floatToFixed((float)CLOCKS_PER_SEC / 30.0f);
}
else if (mode == FIFTY_FRAMES)
{
scaler.floatToFixed((float)CLOCKS_PER_SEC / 50.0f);
}
else if (mode == SIXTY_FRAMES)
{
scaler.floatToFixed((float)CLOCKS_PER_SEC / 60.0f);
}
else if (mode == NANO_SECONDS)
{
scaler.floatToFixed(CLOCKS_PER_SEC / 1000000000);
}
else if (mode == MICRO_SECONDS)
{
scaler.floatToFixed(CLOCKS_PER_SEC / 1000000);
}
else if (mode == MILLI_SECONDS)
{
scaler.floatToFixed(CLOCKS_PER_SEC / 1000);
}
else if (mode == CENTI_SECONDS)
{
scaler.floatToFixed(CLOCKS_PER_SEC / 100);
}
else if (mode == DECI_SECONDS)
{
scaler.floatToFixed(CLOCKS_PER_SEC / 10);
}
else if (mode == SECONDS)
{
scaler.floatToFixed(CLOCKS_PER_SEC);
}
else if (mode == MINUTES)
{
scaler.floatToFixed(CLOCKS_PER_SEC * 60);
}
else if (mode == HOURS)
{
scaler.floatToFixed(CLOCKS_PER_SEC * 60 * 60);
}
#endif
}
And finally where I actually use the classes:
CODE
bool Engine::stateLoop()
{
// Check state for exit condition
if(state->getNullifyState())
{
state->nullifyState();
return false; // End program execution
}
else if (state->getNeedInit() == false)
{
// Update timer
gameTimer.update();
if(gameTimer.getRemaining() <= 0)
{
// Update physics
state->update();
// Take input
state->keyboard();
// Render objects
state->render(screen);
gameTimer.setLimit(1);
}
else
{
SDL_Delay(1); // Release CPU briefly
}
return true; // Continue program execution
}
else
{
// check and change states
getVariables();
state->clear();
stateManagement();
setVariables();
// Initialise the changed state
state->init();
state->setNeedInit(false); // Set that we have performed the init
return true; // Continue program execution
}
// Should never reach here
return false;
}