[Fix] .gitignore decided not to add recursively add /Unuk/srs/libUnuk ...
This commit is contained in:
parent
4e94b83ac6
commit
0078e2aeaa
92
src/libUnuk/Engine/AStar.cpp
Normal file
92
src/libUnuk/Engine/AStar.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include "AStar.h"
|
||||
|
||||
AStar::AStar(void) {
|
||||
while(_openList.size() > 0) {
|
||||
_openList.pop();
|
||||
}
|
||||
_closedList.clear();
|
||||
_solution.clear();
|
||||
}
|
||||
|
||||
AStar::~AStar(void) {
|
||||
AStarBase* best = 0;
|
||||
while(_openList.size() > 0) {
|
||||
best = _openList.top();
|
||||
_openList.pop();
|
||||
delete best;
|
||||
}
|
||||
_closedList.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* Solved the situation given by the initial state with AStar,
|
||||
* and returns a vector of AStarBase that solves the problem.
|
||||
*/
|
||||
std::vector<AStarBase*> AStar::Solve(AStarBase* initState) {
|
||||
AStarBase* best = 0;
|
||||
while(_openList.size() > 0) {
|
||||
best = _openList.top();
|
||||
_openList.pop();
|
||||
delete best;
|
||||
}
|
||||
_closedList.clear();
|
||||
|
||||
_openList.push(initState);
|
||||
return GetSolutionSequence(Search());
|
||||
}
|
||||
|
||||
// Search for the best path.
|
||||
AStarBase* AStar::Search(void) {
|
||||
AStarBase* best = 0;
|
||||
long key = 0;
|
||||
std::vector<AStarBase*> child;
|
||||
|
||||
while(_openList.size() > 0) {
|
||||
while(_closedList.find(key) != _closedList.end()) {
|
||||
// Take the best state, and check if it is on the closed list.
|
||||
if(_openList.size() > 0) {
|
||||
best = _openList.top();
|
||||
_openList.pop();
|
||||
} else
|
||||
return 0;
|
||||
|
||||
key = best->CalculateKey();
|
||||
}
|
||||
|
||||
// Put best on the closed list.
|
||||
_closedList[key] = best;
|
||||
|
||||
// Check if best is our goal.
|
||||
if(best->isGoal())
|
||||
return best;
|
||||
|
||||
// Generate the children.
|
||||
child = best->GenerateChildren();
|
||||
for(unsigned int i = 0; i < child.size(); i++) {
|
||||
_openList.push(child[i]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Generate a solution sequence for a given state.
|
||||
std::vector<AStarBase*> AStar::GetSolutionSequence(AStarBase* node) {
|
||||
_solution.clear();
|
||||
AStarBase* state = node;
|
||||
|
||||
while(state != 0) {
|
||||
_closedList.erase(state->_key);
|
||||
_solution.insert(_solution.begin(), state);
|
||||
state = state->_parent;
|
||||
}
|
||||
|
||||
// Delete the states which are not part of the solution.
|
||||
while(_closedList.size() > 0) {
|
||||
state = _closedList.begin()->second;
|
||||
_closedList.erase(state->_key);
|
||||
delete state;
|
||||
}
|
||||
|
||||
return _solution;
|
||||
}
|
||||
|
30
src/libUnuk/Engine/AStar.h
Normal file
30
src/libUnuk/Engine/AStar.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
#include "AStarBase.h"
|
||||
|
||||
class AStar {
|
||||
public:
|
||||
AStar(void);
|
||||
~AStar(void);
|
||||
|
||||
std::vector<AStarBase*> Solve(AStarBase* initState);
|
||||
|
||||
private:
|
||||
// Comparison structure.
|
||||
struct Cmp : public std::binary_function<AStarBase*, AStarBase*, bool> {
|
||||
bool operator()(AStarBase* a1, AStarBase* a2) const {
|
||||
return (a1->_totalEstimatedCost >= a2->_totalEstimatedCost);
|
||||
}
|
||||
};
|
||||
|
||||
std::priority_queue<AStarBase*, std::vector<AStarBase*>, Cmp > _openList;
|
||||
std::map<const long, AStarBase*> _closedList;
|
||||
|
||||
AStarBase* Search(void);
|
||||
|
||||
std::vector<AStarBase*> GetSolutionSequence(AStarBase* node);
|
||||
std::vector<AStarBase*> _solution;
|
||||
};
|
26
src/libUnuk/Engine/AStarBase.h
Normal file
26
src/libUnuk/Engine/AStarBase.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
class AStarBase {
|
||||
public:
|
||||
AStarBase(void) { };
|
||||
virtual ~AStarBase(void) { };
|
||||
|
||||
// Generate a unique key.
|
||||
virtual long CalculateKey(void) = 0;
|
||||
|
||||
// Aproximate the heuristic cost to the goal.
|
||||
virtual double Estimate(void) = 0;
|
||||
|
||||
// Have we reached the goal?
|
||||
virtual bool isGoal(void) = 0;
|
||||
|
||||
virtual std::vector<AStarBase*> GenerateChildren(void) = 0;
|
||||
|
||||
AStarBase* _parent;
|
||||
|
||||
double _pastCost;
|
||||
double _totalEstimatedCost;
|
||||
|
||||
long _key;
|
||||
};
|
204
src/libUnuk/Engine/Character.cpp
Normal file
204
src/libUnuk/Engine/Character.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
#include "Character.h"
|
||||
|
||||
// Pixels * 60 / sec
|
||||
const float Character::CHARACTER_SPEED = 3.5f;
|
||||
|
||||
static list<Character*>collisionList;
|
||||
static list<Character*>::iterator collisionIter;
|
||||
|
||||
Character::Character(Map* mapArg) {
|
||||
map = mapArg;
|
||||
attacking = false;
|
||||
directionFacing = FACING_DOWN;
|
||||
_animationStage = ANIM_NO_FOOT;
|
||||
_animationTimer.Start();
|
||||
_leftFoot = false;
|
||||
_health = 100;
|
||||
|
||||
xVel = 0.0f;
|
||||
yVel = 0.0f;
|
||||
|
||||
_texture = NULL;
|
||||
|
||||
collisionList.push_front(this);
|
||||
}
|
||||
|
||||
Character::~Character(void) {
|
||||
SDL_FreeSurface(_texture);
|
||||
for(collisionIter = collisionList.begin(); collisionIter != collisionList.end(); collisionIter++) {
|
||||
if((*collisionIter) == this) {
|
||||
collisionList.erase(collisionIter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Character::LoadSprites(string filename, int wArg, int hArg) {
|
||||
if(_texture != NULL)
|
||||
SDL_FreeSurface(_texture);
|
||||
|
||||
_texture = LoadImageAlpha(filename.c_str());
|
||||
|
||||
w = (float)wArg;
|
||||
h = (float)hArg;
|
||||
|
||||
for(int m_direction = 0; m_direction < 4; m_direction++) {
|
||||
for(int m_action = 0; m_action < 4; m_action++) {
|
||||
_sprites[m_direction][m_action].x = (Sint16)(w * m_action);
|
||||
_sprites[m_direction][m_action].y = (Sint16)(h * m_direction);
|
||||
_sprites[m_direction][m_action].w = (Sint16)w;
|
||||
_sprites[m_direction][m_action].h = (Sint16)h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Character::AddSpeachBubble(string text) {
|
||||
_speachBubble.push_back(text);
|
||||
|
||||
_speachBubbleText.SetLineWidth(200);
|
||||
_speachBubbleText.SetTextBlended(text, small, 0, 0, 0, true);
|
||||
|
||||
if(_speachBubbleTimer.IsStarted() == false)
|
||||
_speachBubbleTimer.Start();
|
||||
}
|
||||
|
||||
void Character::Render(void) {
|
||||
// Draw some fancy speach bubbles. It is a bit of a mess, I am playing.
|
||||
if(_speachBubble.size() != 0) {
|
||||
if(_speachBubbleTimer.GetTicks() < SPEACH_BUBBLE_DISPLAY_LENGTH) {
|
||||
roundedBoxRGBA(screen, (Sint16)((x + w / 2) - 100 - camera.x),
|
||||
(Sint16)(y - 100 - camera.y),
|
||||
(Sint16)((x + w / 2) + 100 - camera.x),
|
||||
(Sint16)(y - 35 - camera.y),
|
||||
5, 255, 255, 255, 255);
|
||||
|
||||
filledTrigonRGBA(screen, (Sint16)((x + w / 2) - 100 - camera.x),
|
||||
(Sint16)(y - 100 - camera.y),
|
||||
(Sint16)((x + w / 2) - 10 - camera.x),
|
||||
(Sint16)(y - 40 - camera.y),
|
||||
(Sint16)((x + w / 2) + 10 - camera.x),
|
||||
(Sint16)(y - 40 - camera.y),
|
||||
255, 255, 255, 255);
|
||||
|
||||
_speachBubbleText.Render((int)((x + w / 2) - 90), (int)y - 90);
|
||||
}
|
||||
}
|
||||
|
||||
if(attacking && attackTimer.GetTicks() < ATTACKING_DISPLAY_LEN) {
|
||||
ApplySurface((int)x, (int)y, _texture, screen, &_sprites[directionFacing][ANIM_ATTACK]);
|
||||
return;
|
||||
}
|
||||
else if(attacking)
|
||||
attacking = false;
|
||||
|
||||
if(xVel == 0.0f && yVel == 0.0f)
|
||||
ApplySurface((int)x, (int)y, _texture, screen, &_sprites[directionFacing][ANIM_NO_FOOT]);
|
||||
else {
|
||||
if(_animationTimer.GetTicks() > ANIMATION_SPEED) {
|
||||
if(_animationStage == ANIM_NO_FOOT) {
|
||||
if(_leftFoot == true)
|
||||
_animationStage = ANIM_RIGHT_FOOT;
|
||||
else
|
||||
_animationStage = ANIM_LEFT_FOOT;
|
||||
}
|
||||
else if(_animationStage == ANIM_LEFT_FOOT) {
|
||||
_animationStage = ANIM_NO_FOOT;
|
||||
_leftFoot = true;
|
||||
}
|
||||
else if(_animationStage == ANIM_RIGHT_FOOT) {
|
||||
_animationStage = ANIM_NO_FOOT;
|
||||
_leftFoot = false;
|
||||
}
|
||||
_animationTimer.Start();
|
||||
}
|
||||
ApplySurface((int)x, (int)y, _texture, screen, &_sprites[directionFacing][_animationStage]);
|
||||
}
|
||||
}
|
||||
|
||||
void Character::Update(void) {
|
||||
Move();
|
||||
|
||||
if(_speachBubble.size() != 0) {
|
||||
if(_speachBubbleTimer.GetTicks() > SPEACH_BUBBLE_DISPLAY_LENGTH) {
|
||||
_speachBubble.pop_front();
|
||||
|
||||
if(_speachBubble.size() != 0) {
|
||||
_speachBubbleTimer.Start();
|
||||
}
|
||||
} else {
|
||||
if(_speachBubble.front() != _speachBubbleText.GetText()) {
|
||||
_speachBubbleText.SetTextBlended(_speachBubble.front(), small, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Character::Move(void) {
|
||||
x += xVel;
|
||||
tileX = (int)(((x + (w / 2)) / TILE_WIDTH));
|
||||
tileY = (int)(((y + (h / 2)) / TILE_HEIGHT));
|
||||
|
||||
// Check collisions.
|
||||
if((x < 0) || (x + w) > levelWidth || (x + w) > SCREEN_WIDTH) x -= xVel;
|
||||
if(CheckTileCollisions()) x -= xVel;
|
||||
if(CheckEntityCollisions()) x -= xVel;
|
||||
if(CheckCharacterCollisions()) x -= xVel;
|
||||
|
||||
y += yVel;
|
||||
tileX = (int)(((x + (w / 2)) / TILE_WIDTH));
|
||||
tileY = (int)(((y + (h / 2)) / TILE_HEIGHT));
|
||||
|
||||
if((y < 0) || (y + h) > levelHeight || (y + h) > SCREEN_HEIGHT) y -= yVel;
|
||||
if(CheckTileCollisions()) y -= yVel;
|
||||
if(CheckEntityCollisions()) y -= yVel;
|
||||
if(CheckCharacterCollisions()) y -= yVel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bounds checking only included in map.GetTileSolidity() and
|
||||
* map.GetEntitySolidity(). Remember to add bounds checking
|
||||
* if any other map method is used in a similar manner.
|
||||
*/
|
||||
bool Character::CheckTileCollisions(void) {
|
||||
for(int i = -1; i < 2; i++) {
|
||||
for(int j = -1; j < 2; j++) {
|
||||
if(map->GetTileSolidity(tileX + i, tileY + j))
|
||||
if(CheckCollisionXY((int)x, (int)y, (int)w, (int)h, map->GetTileX(tileX + i, tileY + j),
|
||||
map->GetTileY(tileX + i, tileY + j), TILE_WIDTH, TILE_HEIGHT))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Character::CheckEntityCollisions(void) {
|
||||
for(int i = -1; i < 2; i++) {
|
||||
for(int j = -1; j < 2; j++) {
|
||||
if(map->GetEntitySolidity(tileX + i, tileY + j)) {
|
||||
if(CheckCollisionXY((int)x, (int)y, (int)w, (int)h, map->GetEntityX(tileX + i, tileY + j),
|
||||
map->GetEntityY(tileX + i, tileY + j),
|
||||
map->GetEntityWidth(tileX + i, tileY + j),
|
||||
map->GetEntityHeight(tileX + i, tileY + j)))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Character::CheckCharacterCollisions(void) {
|
||||
for(collisionIter = collisionList.begin();
|
||||
collisionIter != collisionList.end();
|
||||
collisionIter++) {
|
||||
if((*collisionIter) != this) {
|
||||
if(CheckCollisionXY((int)x, (int)y, (int)w, (int)h,
|
||||
(int)(*collisionIter)->GetX(),
|
||||
(int)(*collisionIter)->GetY(),
|
||||
(int)(*collisionIter)->GetWidth(),
|
||||
(int)(*collisionIter)->GetHeight())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
117
src/libUnuk/Engine/Character.h
Normal file
117
src/libUnuk/Engine/Character.h
Normal file
@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_gfxPrimitives.h>
|
||||
#include <list>
|
||||
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "../../Unuk/Constants.h"
|
||||
#include "../Engine/MemClass.h"
|
||||
#include "../Sprite/ApplySurface.h"
|
||||
#include "../Sprite/ImageLoader.h"
|
||||
#include "../Engine/Collision.h"
|
||||
#include "../Map/Map.h"
|
||||
#include "../System/Timer.h"
|
||||
#include "../Ui/Text.h"
|
||||
#include "../System/Debug.h"
|
||||
using namespace std;
|
||||
|
||||
class Map;
|
||||
|
||||
class Character {
|
||||
public:
|
||||
Character(Map* mapArg);
|
||||
~Character(void);
|
||||
|
||||
void LoadSprites(string filename, int wArg, int hArg);
|
||||
|
||||
float GetX(void) { return x; }
|
||||
float GetY(void) { return y; }
|
||||
float GetWidth(void) { return w; }
|
||||
float GetHeight(void) { return h; }
|
||||
|
||||
void SetXY(float xArg, float yArg) { x = xArg, y = yArg; }
|
||||
void SetXVelocity(float arg) { xVel = arg; }
|
||||
void SetYVelocity(float arg) { yVel = arg; }
|
||||
|
||||
void SetHealth(int health) { _health = health; }
|
||||
int GetHealth(void) { return _health; }
|
||||
|
||||
void AddSpeachBubble(string text);
|
||||
|
||||
void Render(void);
|
||||
void Update(void);
|
||||
|
||||
inline void* operator new(size_t size) {
|
||||
return gMemManager.Allocate(size);
|
||||
}
|
||||
|
||||
inline void operator delete(void* object) {
|
||||
gMemManager.Free(object);
|
||||
}
|
||||
|
||||
inline void* operator new [](size_t size) {
|
||||
return gMemManager.Allocate(size);
|
||||
}
|
||||
|
||||
inline void operator delete [](void* object) {
|
||||
gMemManager.Free(object);
|
||||
}
|
||||
|
||||
protected:
|
||||
void Move(void);
|
||||
|
||||
bool CheckTileCollisions(void);
|
||||
bool CheckEntityCollisions(void);
|
||||
bool CheckCharacterCollisions(void);
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float w;
|
||||
float h;
|
||||
|
||||
float xVel;
|
||||
float yVel;
|
||||
|
||||
int tileX;
|
||||
int tileY;
|
||||
|
||||
Timer attackTimer;
|
||||
bool attacking;
|
||||
|
||||
int _health;
|
||||
|
||||
Map* map;
|
||||
|
||||
static const float CHARACTER_SPEED;
|
||||
|
||||
int directionFacing;
|
||||
static const int FACING_UP = 0;
|
||||
static const int FACING_RIGHT = 1;
|
||||
static const int FACING_DOWN = 2;
|
||||
static const int FACING_LEFT = 3;
|
||||
|
||||
static const int ANIM_LEFT_FOOT = 0;
|
||||
static const int ANIM_NO_FOOT = 1;
|
||||
static const int ANIM_RIGHT_FOOT = 2;
|
||||
static const int ANIM_ATTACK = 3;
|
||||
|
||||
private:
|
||||
static const int ANIMATION_SPEED = 200;
|
||||
static const int ATTACKING_DISPLAY_LEN = 150;
|
||||
|
||||
static const int SPEACH_BUBBLE_DISPLAY_LENGTH = 6000;
|
||||
|
||||
SDL_Surface* _texture;
|
||||
|
||||
// [direction][action]
|
||||
SDL_Rect _sprites[4][4];
|
||||
|
||||
Timer _animationTimer;
|
||||
int _animationStage;
|
||||
bool _leftFoot;
|
||||
|
||||
list<string> _speachBubble;
|
||||
list<string>::iterator _speachBubbleIter;
|
||||
Timer _speachBubbleTimer;
|
||||
Text _speachBubbleText;
|
||||
};
|
27
src/libUnuk/Engine/Collision.cpp
Normal file
27
src/libUnuk/Engine/Collision.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "Collision.h"
|
||||
|
||||
bool CheckCollisionRect(SDL_Rect a, SDL_Rect b) {
|
||||
if(a.y + a.h <= b.y)
|
||||
return false;
|
||||
if(a.y >= b.y + b.h)
|
||||
return false;
|
||||
if(a.x + a.w <= b.x)
|
||||
return false;
|
||||
if(a.x >= b.x + b.w)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckCollisionXY(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
|
||||
if(y1 + h1 <= y2)
|
||||
return false;
|
||||
if(y1 >= y2 + h2)
|
||||
return false;
|
||||
if(x1 + w1 <= x2)
|
||||
return false;
|
||||
if(x1 >= x2 + w2)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
6
src/libUnuk/Engine/Collision.h
Normal file
6
src/libUnuk/Engine/Collision.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#define _COLLISION_H_
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
bool CheckCollisionRect(SDL_Rect a, SDL_Rect b);
|
||||
bool CheckCollisionXY(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2);
|
32
src/libUnuk/Engine/MemClass.h
Normal file
32
src/libUnuk/Engine/MemClass.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "MemManager.h"
|
||||
|
||||
extern MemManager gMemManager;
|
||||
|
||||
class MemClass {
|
||||
public:
|
||||
MemClass(void) : r(0), c(0) {}
|
||||
MemClass(double a, double b): r(a), c(b) {}
|
||||
|
||||
inline void* operator new(size_t size) {
|
||||
return gMemManager.Allocate(size);
|
||||
}
|
||||
|
||||
inline void operator delete(void* object) {
|
||||
gMemManager.Free(object);
|
||||
}
|
||||
|
||||
inline void* operator new [](size_t size) {
|
||||
return gMemManager.Allocate(size);
|
||||
}
|
||||
|
||||
inline void operator delete [](void* object) {
|
||||
gMemManager.Free(object);
|
||||
}
|
||||
|
||||
private:
|
||||
// Real part.
|
||||
double r;
|
||||
// Complex part.
|
||||
double c;
|
||||
};
|
206
src/libUnuk/Engine/MemManager.cpp
Normal file
206
src/libUnuk/Engine/MemManager.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
#include "MemClass.h"
|
||||
#include "MemManager.h"
|
||||
|
||||
MemManager gMemManager;
|
||||
|
||||
void BitMapEntry::SetBit(int position, bool flag) {
|
||||
blocksAvailable += flag ? 1 : -1;
|
||||
int elementNo = position / INT_SIZE;
|
||||
int bitNo = position % INT_SIZE;
|
||||
if(flag)
|
||||
bitMap[elementNo] = bitMap[elementNo] | (1 << bitNo);
|
||||
else
|
||||
bitMap[elementNo] = bitMap[elementNo] & ~(1 << bitNo);
|
||||
}
|
||||
|
||||
void BitMapEntry::SetMultipleBits(int position, bool flag, int count) {
|
||||
blocksAvailable += flag ? count : -count;
|
||||
int elementNo = position / INT_SIZE;
|
||||
int bitNo = position % INT_SIZE;
|
||||
|
||||
int bitSize = (count <= INT_SIZE - bitNo) ? count : INT_SIZE - bitNo;
|
||||
SetRangeOfInt(&bitMap[elementNo], bitNo + bitSize - 1, bitNo, flag);
|
||||
count -= bitSize;
|
||||
if(!count) return;
|
||||
|
||||
int i = ++elementNo;
|
||||
while(count >= 0) {
|
||||
if(count <= INT_SIZE) {
|
||||
SetRangeOfInt(&bitMap[i], count - 1, 0, flag);
|
||||
return;
|
||||
} else
|
||||
bitMap[i] = flag ? unsigned (-1) : 0;
|
||||
count -= 32;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void BitMapEntry::SetRangeOfInt(int* element, int msb, int lsb, bool flag) {
|
||||
if(flag) {
|
||||
int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> INT_SIZE - msb - 1);
|
||||
*element |= mask;
|
||||
} else {
|
||||
int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> INT_SIZE - msb - 1);
|
||||
*element &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
MemClass* BitMapEntry::FirstFreeBlock(size_t size) {
|
||||
for(int i = 0; i < BIT_MAP_ELEMENTS; i++) {
|
||||
if(bitMap[i] == 0)
|
||||
// There aint any bits free.
|
||||
continue;
|
||||
|
||||
// Yield the first bit position. This is a 1
|
||||
// in an int from the right.
|
||||
int result = bitMap[i] & -(bitMap[i]);
|
||||
void* address = 0;
|
||||
int basePos = (INT_SIZE * i);
|
||||
|
||||
switch(result) {
|
||||
// Make the corresponfing bit 0 so block is no longer free.
|
||||
case 0x00000001: return ComplexObjectAddress(basePos + 0);
|
||||
case 0x00000002: return ComplexObjectAddress(basePos + 1);
|
||||
case 0x00000004: return ComplexObjectAddress(basePos + 2);
|
||||
case 0x00000008: return ComplexObjectAddress(basePos + 3);
|
||||
case 0x00000010: return ComplexObjectAddress(basePos + 4);
|
||||
case 0x00000020: return ComplexObjectAddress(basePos + 5);
|
||||
case 0x00000040: return ComplexObjectAddress(basePos + 6);
|
||||
case 0x00000080: return ComplexObjectAddress(basePos + 7);
|
||||
case 0x00000100: return ComplexObjectAddress(basePos + 8);
|
||||
case 0x00000200: return ComplexObjectAddress(basePos + 9);
|
||||
case 0x00000400: return ComplexObjectAddress(basePos + 10);
|
||||
case 0x00000800: return ComplexObjectAddress(basePos + 11);
|
||||
case 0x00001000: return ComplexObjectAddress(basePos + 12);
|
||||
case 0x00002000: return ComplexObjectAddress(basePos + 13);
|
||||
case 0x00004000: return ComplexObjectAddress(basePos + 14);
|
||||
case 0x00008000: return ComplexObjectAddress(basePos + 15);
|
||||
case 0x00010000: return ComplexObjectAddress(basePos + 16);
|
||||
case 0x00020000: return ComplexObjectAddress(basePos + 17);
|
||||
case 0x00040000: return ComplexObjectAddress(basePos + 18);
|
||||
case 0x00080000: return ComplexObjectAddress(basePos + 19);
|
||||
case 0x00100000: return ComplexObjectAddress(basePos + 20);
|
||||
case 0x00200000: return ComplexObjectAddress(basePos + 21);
|
||||
case 0x00400000: return ComplexObjectAddress(basePos + 22);
|
||||
case 0x00800000: return ComplexObjectAddress(basePos + 23);
|
||||
case 0x01000000: return ComplexObjectAddress(basePos + 24);
|
||||
case 0x02000000: return ComplexObjectAddress(basePos + 25);
|
||||
case 0x04000000: return ComplexObjectAddress(basePos + 26);
|
||||
case 0x08000000: return ComplexObjectAddress(basePos + 27);
|
||||
case 0x10000000: return ComplexObjectAddress(basePos + 28);
|
||||
case 0x20000000: return ComplexObjectAddress(basePos + 29);
|
||||
case 0x40000000: return ComplexObjectAddress(basePos + 30);
|
||||
case 0x80000000: return ComplexObjectAddress(basePos + 31);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MemClass* BitMapEntry::ComplexObjectAddress(int pos) {
|
||||
SetBit(pos, false);
|
||||
return &((static_cast<MemClass*>(Head()) + (pos / INT_SIZE)) [INT_SIZE - (pos % INT_SIZE + 1)]);
|
||||
}
|
||||
|
||||
void* BitMapEntry::Head(void) {
|
||||
return gMemManager.GetMemoryPoolList()[index];
|
||||
}
|
||||
|
||||
void* MemManager::Allocate(size_t size) {
|
||||
// None array.
|
||||
if(size == sizeof(MemClass)) {
|
||||
set<BitMapEntry*>::iterator freeMapI = _freeMapEntries.begin();
|
||||
if(freeMapI != _freeMapEntries.end()) {
|
||||
BitMapEntry* mapEntry = *freeMapI;
|
||||
return mapEntry->FirstFreeBlock(size);
|
||||
} else {
|
||||
AllocateChunkAndInitBitMap();
|
||||
_freeMapEntries.insert(&(_bitMapEntryList[_bitMapEntryList.size() - 1]));
|
||||
return _bitMapEntryList[_bitMapEntryList.size() - 1].FirstFreeBlock(size);
|
||||
}
|
||||
} else {
|
||||
// Array.
|
||||
if(_arrayMemoryList.empty()) {
|
||||
return AllocateArrayMemory(size);
|
||||
} else {
|
||||
map<void*, ArrayMemoryInfo>::iterator infoI = _arrayMemoryList.begin();
|
||||
map<void*, ArrayMemoryInfo>::iterator infoEndI = _arrayMemoryList.end();
|
||||
|
||||
while(infoI != infoEndI) {
|
||||
ArrayMemoryInfo info = (*infoI).second;
|
||||
if(info.StartPosition != 0)
|
||||
// Only search the memory blocks where allocation
|
||||
// is done from first byte.
|
||||
continue;
|
||||
else {
|
||||
BitMapEntry* entry = &_bitMapEntryList[info.memPoolListIndex];
|
||||
if(entry->blocksAvailable < (size / sizeof(MemClass)))
|
||||
return AllocateArrayMemory(size);
|
||||
else {
|
||||
info.StartPosition = BIT_MAP_SIZE - entry->blocksAvailable;
|
||||
info.Size = size / sizeof(MemClass);
|
||||
MemClass* baseAddress = static_cast<MemClass*>(_memoryPoolList[info.memPoolListIndex]) + info.StartPosition;
|
||||
|
||||
_arrayMemoryList[baseAddress] = info;
|
||||
SetMultipleBlockBits(&info, false);
|
||||
|
||||
return baseAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* MemManager::AllocateArrayMemory(size_t size) {
|
||||
void* chunkAddress = AllocateChunkAndInitBitMap();
|
||||
ArrayMemoryInfo info;
|
||||
info.memPoolListIndex = _memoryPoolList.size() - 1;
|
||||
info.StartPosition = 0;
|
||||
info.Size = size / sizeof(MemClass);
|
||||
_arrayMemoryList[chunkAddress] = info;
|
||||
SetMultipleBlockBits(&info, false);
|
||||
return chunkAddress;
|
||||
}
|
||||
|
||||
void* MemManager::AllocateChunkAndInitBitMap(void) {
|
||||
BitMapEntry mapEntry;
|
||||
MemClass* memoryBeginAddress = reinterpret_cast<MemClass*>(new char[sizeof(MemClass) * BIT_MAP_SIZE]);
|
||||
_memoryPoolList.push_back(memoryBeginAddress);
|
||||
mapEntry.index = _memoryPoolList.size() - 1;
|
||||
_bitMapEntryList.push_back(mapEntry);
|
||||
return memoryBeginAddress;
|
||||
}
|
||||
|
||||
void MemManager::Free(void* object) {
|
||||
if(_arrayMemoryList.find(object) == _arrayMemoryList.end())
|
||||
// Simple block deletion.
|
||||
SetBlockBit(object, true);
|
||||
else {
|
||||
// Memory block deletion.
|
||||
ArrayMemoryInfo *info = &_arrayMemoryList[object];
|
||||
SetMultipleBlockBits(info, true);
|
||||
}
|
||||
}
|
||||
|
||||
void MemManager::SetBlockBit(void* object, bool flag) {
|
||||
int i = _bitMapEntryList.size() - 1;
|
||||
for(; i >= 0; i--) {
|
||||
BitMapEntry* bitMap = &_bitMapEntryList[i];
|
||||
if((bitMap->Head() <= object) && (&(static_cast<MemClass*>(bitMap->Head()))[BIT_MAP_SIZE - 1] >= object)) {
|
||||
int position = static_cast<MemClass*>(object)- static_cast<MemClass*>(bitMap->Head());
|
||||
bitMap->SetBit(position, flag);
|
||||
flag ? bitMap->blocksAvailable++ : bitMap->blocksAvailable--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemManager::SetMultipleBlockBits(ArrayMemoryInfo* info, bool flag) {
|
||||
BitMapEntry* mapEntry = &_bitMapEntryList[info->memPoolListIndex];
|
||||
mapEntry->SetMultipleBits(info->StartPosition, flag, info->Size);
|
||||
}
|
||||
|
||||
vector<void*>& MemManager::GetMemoryPoolList(void) {
|
||||
return _memoryPoolList;
|
||||
}
|
88
src/libUnuk/Engine/MemManager.h
Normal file
88
src/libUnuk/Engine/MemManager.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <bitset>
|
||||
using namespace std;
|
||||
|
||||
const int BIT_MAP_SIZE = 1024;
|
||||
const int INT_SIZE = sizeof(int) * 8;
|
||||
const int BIT_MAP_ELEMENTS = BIT_MAP_SIZE / INT_SIZE;
|
||||
|
||||
/*
|
||||
* Memory Allocation Pattern.
|
||||
* 11111111 11111111 11111111
|
||||
* 11111110 11111111 11111111
|
||||
* 11111100 11111111 11111111
|
||||
*
|
||||
* If all bits for the first section becomes zero go to next section.
|
||||
*
|
||||
* 00000000 11111111 11111111
|
||||
* 00000000 11111110 11111111
|
||||
* 00000000 11111100 11111111
|
||||
* 00000000 11111000 11111111
|
||||
*
|
||||
* The lookup inside the map becomes 0(1) for the first available free block.
|
||||
*/
|
||||
|
||||
class MemClass;
|
||||
|
||||
typedef struct BitMapEntry {
|
||||
int index;
|
||||
int blocksAvailable;
|
||||
int bitMap[BIT_MAP_SIZE];
|
||||
|
||||
public:
|
||||
BitMapEntry():blocksAvailable(BIT_MAP_SIZE) {
|
||||
// All blocks are free to begin with and bit value 1
|
||||
// in the map denotes available blocks.
|
||||
memset(bitMap, 0xff, BIT_MAP_SIZE / sizeof(char));
|
||||
}
|
||||
|
||||
void SetBit(int position, bool flag);
|
||||
void SetMultipleBits(int position, bool flag, int count);
|
||||
void SetRangeOfInt(int* element, int msb, int lsb, bool flag);
|
||||
MemClass* FirstFreeBlock(size_t size);
|
||||
MemClass* ComplexObjectAddress(int pos);
|
||||
void* Head(void);
|
||||
} BitMapEntry;
|
||||
|
||||
typedef struct ArrayInfo {
|
||||
int memPoolListIndex;
|
||||
int StartPosition;
|
||||
int Size;
|
||||
} ArrayMemoryInfo;
|
||||
|
||||
class IMemManager {
|
||||
public:
|
||||
virtual void* Allocate(size_t size) = 0;
|
||||
virtual void Free(void* object) = 0;
|
||||
};
|
||||
|
||||
class MemManager : public IMemManager {
|
||||
public:
|
||||
MemManager(void) {}
|
||||
~MemManager(void) {}
|
||||
|
||||
void* Allocate(size_t size);
|
||||
void Free(void* object);
|
||||
vector<void*>& GetMemoryPoolList(void);
|
||||
|
||||
private:
|
||||
void* AllocateArrayMemory(size_t size);
|
||||
void* AllocateChunkAndInitBitMap(void);
|
||||
void SetBlockBit(void* object, bool flag);
|
||||
void SetMultipleBlockBits(ArrayMemoryInfo* info, bool flag);
|
||||
|
||||
// The following lists will maintain one to one correspondace
|
||||
// and should be the same size.
|
||||
vector<void*> _memoryPoolList;
|
||||
vector<BitMapEntry> _bitMapEntryList;
|
||||
|
||||
set<BitMapEntry*> _freeMapEntries;
|
||||
map<void*, ArrayMemoryInfo> _arrayMemoryList;
|
||||
};
|
59
src/libUnuk/Engine/NPC.cpp
Normal file
59
src/libUnuk/Engine/NPC.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include "NPC.h"
|
||||
|
||||
NPC::NPC(Map* mapArg) : Character(mapArg) {
|
||||
_moveTimer.Start();
|
||||
|
||||
_moveChangeFrequency = 14000;
|
||||
_moveDurationMax = 3000;
|
||||
_moveDurationMin = 1000;
|
||||
}
|
||||
|
||||
NPC::~NPC(void) {
|
||||
|
||||
}
|
||||
|
||||
void NPC::Update(void) {
|
||||
// Store the NPC's health.
|
||||
// int health = GetHealth(); // not referenced
|
||||
|
||||
Move();
|
||||
|
||||
if(xVel > 0) directionFacing = FACING_RIGHT;
|
||||
else if(xVel < 0) directionFacing = FACING_LEFT;
|
||||
else if(yVel > 0) directionFacing = FACING_DOWN;
|
||||
else if(yVel < 0) directionFacing = FACING_UP;
|
||||
}
|
||||
|
||||
void NPC::Move(void) {
|
||||
if(_moving && _moveTimer.GetTicks() > _moveDurationMax) {
|
||||
xVel = 0.0f;
|
||||
yVel = 0.0f;
|
||||
_moving = false;
|
||||
}
|
||||
|
||||
if(_moving && _moveTimer.GetTicks() >= _moveDurationCurrent) {
|
||||
xVel = 0.0f;
|
||||
yVel = 0.0f;
|
||||
_moving = false;
|
||||
}
|
||||
|
||||
if(_moveTimer.GetTicks() > _moveChangeFrequency) {
|
||||
_moveTimer.Start();
|
||||
_moveDurationCurrent = _moveDurationMin + (rand() % (_moveDurationMax - _moveDurationMin));
|
||||
if(rand() % 2) {
|
||||
yVel = 0.0f;
|
||||
if(rand() % 2)
|
||||
xVel = CHARACTER_SPEED;
|
||||
else
|
||||
xVel = -CHARACTER_SPEED;
|
||||
} else {
|
||||
xVel = 0.0f;
|
||||
if(rand() % 2)
|
||||
yVel = CHARACTER_SPEED;
|
||||
else
|
||||
yVel = -CHARACTER_SPEED;
|
||||
}
|
||||
_moving = true;
|
||||
}
|
||||
Character::Move();
|
||||
}
|
26
src/libUnuk/Engine/NPC.h
Normal file
26
src/libUnuk/Engine/NPC.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "Character.h"
|
||||
#include "AStar.h"
|
||||
|
||||
class NPC : public Character {
|
||||
public:
|
||||
NPC(Map* mapArg);
|
||||
~NPC(void);
|
||||
|
||||
void Update(void);
|
||||
|
||||
protected:
|
||||
void Move(void);
|
||||
|
||||
private:
|
||||
int _moveChangeFrequency;
|
||||
|
||||
int _moveDurationCurrent;
|
||||
int _moveDurationMin;
|
||||
int _moveDurationMax;
|
||||
|
||||
bool _moving;
|
||||
|
||||
Timer _moveTimer;
|
||||
};
|
80
src/libUnuk/Engine/ParticleEmitter.cpp
Normal file
80
src/libUnuk/Engine/ParticleEmitter.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "ParticleEmitter.h"
|
||||
|
||||
ParticleEmitter::ParticleEmitter(void) {
|
||||
|
||||
}
|
||||
|
||||
ParticleEmitter::~ParticleEmitter(void) {
|
||||
|
||||
}
|
||||
|
||||
void ParticleEmitter::SetXY(int xArg, int yArg) {
|
||||
x = xArg;
|
||||
y = yArg;
|
||||
}
|
||||
|
||||
void ParticleEmitter::ForceXY(int xArg, int yArg) {
|
||||
for(int i = 0; i < _particleCount; i++) {
|
||||
m_particle[i].x = (float)xArg;
|
||||
m_particle[i].y = (float)yArg;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEmitter::SetParticleCount(int countArg) {
|
||||
_particleCount = countArg;
|
||||
m_particle.resize(_particleCount);
|
||||
|
||||
for(int i = 0; i < _particleCount; i++) {
|
||||
m_particle[i].startTime = SDL_GetTicks();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEmitter::SetParticleSpeed(float speedArg) {
|
||||
_particleSpeed = speedArg;
|
||||
}
|
||||
|
||||
void ParticleEmitter::SetParticleType(string typeArg) {
|
||||
if(!_particleTexture) {
|
||||
SDL_FreeSurface(_particleTexture);
|
||||
}
|
||||
|
||||
string textureFilename = "../Data/Media/Images/Particles/" + typeArg + ".png";
|
||||
_particleTexture = LoadImageAlpha(textureFilename.c_str());
|
||||
}
|
||||
|
||||
void ParticleEmitter::SetParticleLifetime(int lifetimeArg) {
|
||||
_particleLifetime = lifetimeArg;
|
||||
|
||||
for(int i = 0; i < _particleCount; i++) {
|
||||
m_particle[i].lifetime = rand() % _particleLifetime + _particleLifetime / 4;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEmitter::Render(void) {
|
||||
for(int i = 0; i < _particleCount; i++) {
|
||||
ApplySurface((int)m_particle[i].x, (int)m_particle[i].y, _particleTexture, screen);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEmitter::Update(void) {
|
||||
for(int i = 0; i < _particleCount; i++) {
|
||||
if((int)SDL_GetTicks() - m_particle[i].startTime > m_particle[i].lifetime) {
|
||||
// Reset the x and y coords.
|
||||
m_particle[i].x = (float)x;
|
||||
m_particle[i].y = (float)y;
|
||||
|
||||
m_particle[i].xVel = (float)(rand() % 360);
|
||||
m_particle[i].yVel = (float)(rand() % 360);
|
||||
|
||||
if(rand() % 2)
|
||||
m_particle[i].xVel = m_particle[i].xVel * -1.0f;
|
||||
if(rand() % 2)
|
||||
m_particle[i].yVel = m_particle[i].yVel * -1.0f;
|
||||
|
||||
m_particle[i].startTime = SDL_GetTicks();
|
||||
} else {
|
||||
m_particle[i].x += m_particle[i].xVel * _particleSpeed;
|
||||
m_particle[i].y += m_particle[i].yVel * _particleSpeed;
|
||||
}
|
||||
}
|
||||
}
|
52
src/libUnuk/Engine/ParticleEmitter.h
Normal file
52
src/libUnuk/Engine/ParticleEmitter.h
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "../Sprite/ImageLoader.h"
|
||||
#include "../Sprite/ApplySurface.h"
|
||||
using namespace std;
|
||||
|
||||
struct Particle {
|
||||
float x;
|
||||
float y;
|
||||
|
||||
float xVel;
|
||||
float yVel;
|
||||
|
||||
int lifetime;
|
||||
int startTime;
|
||||
};
|
||||
|
||||
class ParticleEmitter {
|
||||
public:
|
||||
ParticleEmitter(void);
|
||||
~ParticleEmitter(void);
|
||||
|
||||
// distribute particles from the new x and y.
|
||||
void SetXY(int xArg, int yArg);
|
||||
// Move all the existing particles to the new x and y.
|
||||
void ForceXY(int xArg, int yArg);
|
||||
|
||||
void SetParticleCount(int countArg);
|
||||
void SetParticleLifetime(int lifetimeArg);
|
||||
void SetParticleSpeed(float speedArg);
|
||||
void SetParticleType(string typeArg);
|
||||
|
||||
void Render(void);
|
||||
void Update(void);
|
||||
|
||||
private:
|
||||
vector<Particle> m_particle;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
|
||||
int _particleCount;
|
||||
int _particleLifetime;
|
||||
float _particleSpeed;
|
||||
|
||||
SDL_Surface* _particleTexture;
|
||||
};
|
54
src/libUnuk/Engine/WorldManager.cpp
Normal file
54
src/libUnuk/Engine/WorldManager.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "WorldManager.h"
|
||||
#include "NPC.h"
|
||||
|
||||
WorldManager::WorldManager(void) {
|
||||
}
|
||||
|
||||
WorldManager::~WorldManager(void) {
|
||||
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
|
||||
NPC* npc = (*i);
|
||||
delete npc;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldManager::Update(void) {
|
||||
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
|
||||
NPC* npc = (*i);
|
||||
npc->Update();
|
||||
}
|
||||
}
|
||||
|
||||
void WorldManager::Render(void) {
|
||||
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
|
||||
NPC* npc = (*i);
|
||||
npc->Render();
|
||||
}
|
||||
}
|
||||
|
||||
void WorldManager::AddNPC(NPC* npc) {
|
||||
_npcs.push_back(npc);
|
||||
}
|
||||
|
||||
void WorldManager::RemoveNPC(int index) {
|
||||
int npcsIndex = 0;
|
||||
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
|
||||
NPC* npc = (*i);
|
||||
if(npcsIndex == index) {
|
||||
_npcs.erase(i);
|
||||
delete npc;
|
||||
}
|
||||
npcsIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
NPC* WorldManager::GetNPC(int index) {
|
||||
int npcsIndex = 0;
|
||||
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
|
||||
NPC* npc = (*i);
|
||||
if(npcsIndex == index) {
|
||||
return npc;
|
||||
}
|
||||
npcsIndex++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
20
src/libUnuk/Engine/WorldManager.h
Normal file
20
src/libUnuk/Engine/WorldManager.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
|
||||
class NPC;
|
||||
|
||||
class WorldManager {
|
||||
public:
|
||||
WorldManager(void);
|
||||
~WorldManager(void);
|
||||
|
||||
void Update(void);
|
||||
void Render(void);
|
||||
|
||||
void AddNPC(NPC* npc);
|
||||
void RemoveNPC(int index);
|
||||
NPC* GetNPC(int index);
|
||||
|
||||
private:
|
||||
std::list<NPC*> _npcs;
|
||||
};
|
251
src/libUnuk/Map/Map.cpp
Normal file
251
src/libUnuk/Map/Map.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
#include "Map.h"
|
||||
#include "../Engine/NPC.h"
|
||||
|
||||
Map::Map(void) {
|
||||
|
||||
}
|
||||
|
||||
Map::~Map(void) {
|
||||
|
||||
}
|
||||
|
||||
void Map::Load(const string filename) {
|
||||
Unload();
|
||||
_currentMap = filename;
|
||||
string fullMapPath = "../Data/Media/Maps/" + filename;
|
||||
TiXmlDocument mapFile(fullMapPath.c_str());
|
||||
|
||||
assert(mapFile.LoadFile() == true);
|
||||
|
||||
// Getting dirty with some XML. This seems like a nicer
|
||||
// approach to loading maps, rather than parsing tet files.
|
||||
TiXmlElement* rootElem = NULL;
|
||||
TiXmlElement* lineElem = NULL;
|
||||
TiXmlElement* tileElem = NULL;
|
||||
TiXmlElement* dataElem = NULL;
|
||||
|
||||
x = -1;
|
||||
y = -1;
|
||||
|
||||
// <map> - Let's start parsing the map.
|
||||
rootElem = mapFile.FirstChildElement("map");
|
||||
assert(rootElem != NULL);
|
||||
if(rootElem) {
|
||||
// <line> - We want to tile one line at a time. line represents
|
||||
// the row we are tiling.
|
||||
lineElem = rootElem->FirstChildElement("line");
|
||||
assert(lineElem != NULL);
|
||||
while(lineElem) {
|
||||
y++;
|
||||
x = -1;
|
||||
|
||||
// <tile> - Then we will select the tile. and increment x to keep tiling that row.
|
||||
tileElem = lineElem->FirstChildElement("tile");
|
||||
assert(tileElem != NULL);
|
||||
while(tileElem) {
|
||||
x++;
|
||||
_tile[x][y].SetTileXY(x * TILE_WIDTH, y * TILE_HEIGHT);
|
||||
|
||||
// <tileTexture> - Apply a teture to the tile.
|
||||
dataElem = tileElem->FirstChildElement("tileTexture");
|
||||
assert(dataElem != NULL);
|
||||
stringstream tilePath;
|
||||
tilePath << "../Data/Media/Images/Tiles/" << dataElem->GetText() << ".png";
|
||||
_tile[x][y].SetTileTexture(_tileTextures.Add(tilePath.str()));
|
||||
// <tileTexture> - Finished applying the texture, move to the next sibling.
|
||||
|
||||
// <solidTile> - Check to see if the tile is solid or not.
|
||||
dataElem = dataElem->NextSiblingElement("solidTile");
|
||||
assert(dataElem != NULL);
|
||||
string tileSolidity = dataElem->GetText();
|
||||
assert(tileSolidity == "false" || tileSolidity == "true");
|
||||
if(tileSolidity == "false")
|
||||
_tile[x][y].SetTileSolidity(false);
|
||||
else
|
||||
_tile[x][y].SetTileSolidity(true);
|
||||
// </solidTile>
|
||||
|
||||
// <entityTexture>
|
||||
dataElem = dataElem->NextSiblingElement("entityTexture");
|
||||
assert(dataElem != NULL);
|
||||
string entityName = dataElem->GetText();
|
||||
if(entityName != "null") {
|
||||
stringstream entityPath;
|
||||
entityPath << "../Data/Media/Images/Entities/" << entityName << ".png";
|
||||
_tile[x][y].SetEntityTexture(_entityTextures.AddAlpha(entityPath.str()));
|
||||
|
||||
_tile[x][y].SetEntityXY(_tile[x][y].GetTileX() + TILE_WIDTH / 2 - _tile[x][y].GetEntityWidth() / 2,
|
||||
_tile[x][y].GetTileY() + TILE_HEIGHT / 2 - _tile[x][y].GetEntityHeight() / 2);
|
||||
}
|
||||
// </entityTexture>
|
||||
|
||||
// <SolidEntity>
|
||||
dataElem = dataElem->NextSiblingElement("solidEntity");
|
||||
assert(dataElem != NULL);
|
||||
string entitySolidity = dataElem->GetText();
|
||||
assert(entitySolidity == "false" || entitySolidity == "true");
|
||||
if(entitySolidity == "false")
|
||||
_tile[x][y].SetEntitySolidity(false);
|
||||
else
|
||||
_tile[x][y].SetEntitySolidity(true);
|
||||
// </solidEntity>
|
||||
|
||||
// <zlevel>
|
||||
dataElem = dataElem->NextSiblingElement("zLevel");
|
||||
assert(dataElem != NULL);
|
||||
_tile[x][y].SetZLevel(atoi(dataElem->GetText()));
|
||||
// </zlevel>
|
||||
|
||||
// <mapTransition>
|
||||
dataElem = dataElem->NextSiblingElement("mapTransition");
|
||||
assert(dataElem != NULL);
|
||||
_tile[x][y].SetMapTransitionName(dataElem->GetText());
|
||||
// </mapTransition>
|
||||
|
||||
// <mapTransX>
|
||||
dataElem = dataElem->NextSiblingElement("mapTransX");
|
||||
assert(dataElem != NULL);
|
||||
// int mapTransX = atoi(dataElem->GetText()); // not referenced
|
||||
// </mapTransX>
|
||||
|
||||
// <mapTransY>
|
||||
dataElem = dataElem->NextSiblingElement("mapTransY");
|
||||
assert(dataElem != NULL);
|
||||
// int mapTransY = atoi(dataElem->GetText()); // not referenced
|
||||
// </mapTransY>
|
||||
|
||||
tileElem = tileElem->NextSiblingElement("tile");
|
||||
}
|
||||
//</tile>
|
||||
|
||||
lineElem = lineElem->NextSiblingElement("line");
|
||||
}
|
||||
// </line>
|
||||
}
|
||||
// </map>
|
||||
levelWidth = x * TILE_WIDTH;
|
||||
levelHeight = y * TILE_HEIGHT;
|
||||
|
||||
//character->Load(filename);
|
||||
|
||||
NPC* npc = new NPC(this);
|
||||
|
||||
npc->SetXY(300, 300);
|
||||
npc->LoadSprites("../Data/Media/Images/Characters/template.png", 40,45);
|
||||
_world.AddNPC(npc);
|
||||
|
||||
npc = new NPC(this);
|
||||
npc->SetXY(150, 350);
|
||||
npc->LoadSprites("../Data/Media/Images/Characters/template.png", 40,45);
|
||||
_world.AddNPC(npc);
|
||||
|
||||
npc = new NPC(this);
|
||||
npc->SetXY(100, 250);
|
||||
npc->LoadSprites("../Data/Media/Images/Characters/template.png", 40,45);
|
||||
_world.AddNPC(npc);
|
||||
}
|
||||
|
||||
void Map::Update(void) {
|
||||
_world.Update();
|
||||
// Update the map so we can render when camera moves.
|
||||
}
|
||||
|
||||
void Map::Render(void) {
|
||||
int xOrig = (camera.x / TILE_WIDTH) - 1;
|
||||
int yOrig = (camera.y / TILE_HEIGHT) - 1;
|
||||
|
||||
if (xOrig < 0) xOrig = 0;
|
||||
if (yOrig < 0) yOrig = 0;
|
||||
|
||||
int xEnd = xOrig + (SCREEN_WIDTH / TILE_WIDTH) + 3;
|
||||
int yEnd = yOrig + (SCREEN_HEIGHT / TILE_HEIGHT) + 3;
|
||||
|
||||
/* the fuck is this Allanis? --konom
|
||||
if(xEnd < x)
|
||||
xEnd++;
|
||||
else
|
||||
xEnd = x;
|
||||
|
||||
if(yEnd < y)
|
||||
yEnd++;
|
||||
else
|
||||
yEnd = y;
|
||||
*/
|
||||
|
||||
if (xEnd > x) xEnd = x;
|
||||
if (yEnd > y) yEnd = y;
|
||||
if (xEnd < 0) xEnd = 0;
|
||||
if (yEnd < 0) yEnd = 0;
|
||||
|
||||
if (xOrig > xEnd) xOrig = xEnd - 1;
|
||||
if (yOrig > yEnd) yOrig = yEnd - 1;
|
||||
|
||||
for(int i = xOrig; i < xEnd; i++) {
|
||||
for(int j = yOrig; j < yEnd; j++) {
|
||||
_tile[i][j].Render();
|
||||
}
|
||||
}
|
||||
|
||||
_world.Render();
|
||||
}
|
||||
|
||||
void Map::Unload(void) {
|
||||
_tileTextures.Unload();
|
||||
_entityTextures.Unload();
|
||||
}
|
||||
|
||||
string Map::GetCurrentMap(void) {
|
||||
return _currentMap;
|
||||
}
|
||||
|
||||
bool Map::GetTileSolidity(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetTileSolidity();
|
||||
}
|
||||
|
||||
int Map::GetTileX(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetTileX();
|
||||
}
|
||||
|
||||
int Map::GetTileY(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetTileY();
|
||||
}
|
||||
|
||||
bool Map::GetEntitySolidity(int xArg, int yArg) {
|
||||
if(xArg > x || yArg > y || yArg < 0 || yArg < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _tile[xArg + 1][yArg + 1].GetEntitySolitity();
|
||||
}
|
||||
|
||||
int Map::GetEntityX(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetEntityX();
|
||||
}
|
||||
|
||||
int Map::GetEntityY(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetEntityY();
|
||||
}
|
||||
|
||||
int Map::GetEntityWidth(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetEntityWidth();
|
||||
}
|
||||
|
||||
int Map::GetEntityHeight(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetEntityHeight();
|
||||
}
|
||||
|
||||
int Map::GetTileZLevel(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetZLevel();
|
||||
}
|
||||
|
||||
string Map::GetMapTransitionName(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetMapTransitionName();
|
||||
}
|
||||
|
||||
int Map::GetMapTransitionX(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetMapTransitionX();
|
||||
}
|
||||
|
||||
int Map::GetMapTransitionY(int xArg, int yArg) {
|
||||
return _tile[xArg + 1][yArg + 1].GetMapTransitionY();
|
||||
}
|
64
src/libUnuk/Map/Map.h
Normal file
64
src/libUnuk/Map/Map.h
Normal file
@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <assert.h>
|
||||
#include <tinyxml.h>
|
||||
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "../../Unuk/Constants.h"
|
||||
#include "../Sprite/ImageLoader.h"
|
||||
#include "../Sprite/ApplySurface.h"
|
||||
#include "../Map/MapTile.h"
|
||||
#include "../System/Debug.h"
|
||||
#include "../Engine/WorldManager.h"
|
||||
using namespace std;
|
||||
|
||||
//class CharacterManager;
|
||||
|
||||
class Map {
|
||||
public:
|
||||
Map(void);
|
||||
~Map(void);
|
||||
|
||||
void Load(const string filename);
|
||||
void Update(void);
|
||||
void Render(void);
|
||||
|
||||
bool GetTileSolidity(int xArg, int yArg);
|
||||
int GetTileX(int xArg, int yArg);
|
||||
int GetTileY(int xArg, int yArg);
|
||||
|
||||
bool GetEntitySolidity(int xArg, int yArg);
|
||||
int GetEntityX(int xArg, int yArg);
|
||||
int GetEntityY(int xArg, int yArg);
|
||||
int GetEntityWidth(int xArg, int yArg);
|
||||
int GetEntityHeight(int xArg, int yArg);
|
||||
|
||||
int GetTileZLevel(int xArg, int yArg);
|
||||
|
||||
string GetMapTransitionName(int xArg, int yArg);
|
||||
int GetMapTransitionX(int xArg, int yArg);
|
||||
int GetMapTransitionY(int xArg, int yArg);
|
||||
|
||||
string GetCurrentMap(void);
|
||||
|
||||
WorldManager& GetWorld(void) { return _world; }
|
||||
|
||||
private:
|
||||
void Unload(void);
|
||||
|
||||
string _currentMap;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
static const int TILE_ARRAY_SIZE = 150;
|
||||
MapTile _tile[TILE_ARRAY_SIZE][TILE_ARRAY_SIZE];
|
||||
|
||||
TextureManager _tileTextures;
|
||||
TextureManager _entityTextures;
|
||||
|
||||
WorldManager _world;
|
||||
};
|
39
src/libUnuk/Map/MapElement.cpp
Normal file
39
src/libUnuk/Map/MapElement.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "MapElement.h"
|
||||
|
||||
MapElement::MapElement(void) {
|
||||
|
||||
}
|
||||
|
||||
MapElement::~MapElement(void) {
|
||||
|
||||
}
|
||||
|
||||
void MapElement::SetTexture(SDL_Surface* arg) {
|
||||
_texture = arg;
|
||||
}
|
||||
|
||||
void MapElement::Render(void) {
|
||||
ApplySurface(x, y, _texture, screen);
|
||||
}
|
||||
|
||||
void MapElement::Update(void) {
|
||||
|
||||
}
|
||||
|
||||
void MapElement::SetSolidity(bool arg) {
|
||||
_solid = arg;
|
||||
}
|
||||
|
||||
bool MapElement::GetSolidity(void) {
|
||||
return _solid;
|
||||
}
|
||||
|
||||
void MapElement::SetXY(int xArg, int yArg) {
|
||||
x = xArg,
|
||||
y = yArg;
|
||||
}
|
||||
|
||||
int MapElement::GetX(void) { return x; }
|
||||
int MapElement::GetY(void) { return y; }
|
||||
int MapElement::GetWidth(void) { return _texture->w; }
|
||||
int MapElement::GetHeight(void) { return _texture->h; }
|
36
src/libUnuk/Map/MapElement.h
Normal file
36
src/libUnuk/Map/MapElement.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <string>
|
||||
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "../Sprite/ApplySurface.h"
|
||||
#include "../Sprite/TextureManager.h"
|
||||
|
||||
class MapElement {
|
||||
public:
|
||||
MapElement(void);
|
||||
~MapElement(void);
|
||||
|
||||
static void SetTextureManager(TextureManager* arg);
|
||||
|
||||
virtual void SetTexture(SDL_Surface* arg);
|
||||
virtual void Render(void);
|
||||
virtual void Update(void);
|
||||
|
||||
void SetSolidity(bool arg);
|
||||
bool GetSolidity(void);
|
||||
|
||||
void SetXY(int xArg, int yArg);
|
||||
int GetX(void);
|
||||
int GetY(void);
|
||||
int GetWidth(void);
|
||||
int GetHeight(void);
|
||||
|
||||
protected:
|
||||
SDL_Surface* _texture;
|
||||
|
||||
bool _solid;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
};
|
16
src/libUnuk/Map/MapEntities.cpp
Normal file
16
src/libUnuk/Map/MapEntities.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "MapEntities.h"
|
||||
|
||||
MapEntityGeneric::MapEntityGeneric(void) {
|
||||
_texture = NULL;
|
||||
|
||||
}
|
||||
|
||||
MapEntityGeneric::~MapEntityGeneric(void) {
|
||||
|
||||
}
|
||||
|
||||
void MapEntityGeneric::Render(void) {
|
||||
if(_texture != NULL) {
|
||||
MapElement::Render();
|
||||
}
|
||||
}
|
19
src/libUnuk/Map/MapEntities.h
Normal file
19
src/libUnuk/Map/MapEntities.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Version of MapElement, that will check whether the SDL_Surface it
|
||||
* owns is NULL or not and draws.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MapElement.h"
|
||||
|
||||
class MapEntityGeneric : public MapElement {
|
||||
public:
|
||||
MapEntityGeneric(void);
|
||||
~MapEntityGeneric(void);
|
||||
|
||||
void Render(void);
|
||||
|
||||
private:
|
||||
|
||||
};
|
66
src/libUnuk/Map/MapTile.h
Normal file
66
src/libUnuk/Map/MapTile.h
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include "../../Unuk/Constants.h"
|
||||
#include "../Sprite/ApplySurface.h"
|
||||
#include "../Map/MapElement.h"
|
||||
#include "../Map/MapEntities.h"
|
||||
using namespace std;
|
||||
|
||||
class MapTile {
|
||||
public:
|
||||
MapTile(void) { }
|
||||
~MapTile(void) { }
|
||||
|
||||
void Render(void) { _tile.Render(), _entity.Render(); }
|
||||
|
||||
// Tile Mutators.
|
||||
SDL_Surface* SetTileTexture(SDL_Surface* arg) { _tile.SetTexture(arg); return NULL; }
|
||||
void SetTileSolidity(bool arg) { _tile.SetSolidity(arg); }
|
||||
bool GetTileSolidity(void) { return _tile.GetSolidity(); }
|
||||
// Well, it kinda helps if I lay the
|
||||
// tiles rather than just get the
|
||||
// return value right??
|
||||
void SetTileXY(int xArg, int yArg) { _tile.SetXY(xArg, yArg); }
|
||||
int GetTileX(void) { return _tile.GetX(); }
|
||||
int GetTileY(void) { return _tile.GetY(); }
|
||||
|
||||
// Entity Mutators.
|
||||
void SetEntityTexture(SDL_Surface* arg) { _entity.SetTexture(arg); }
|
||||
void SetEntityXY(int xArg, int yArg) { _entity.SetXY(xArg, yArg); }
|
||||
void SetEntitySolidity(bool arg) { _entity.SetSolidity(arg); }
|
||||
bool GetEntitySolitity(void) { return _entity.GetSolidity(); }
|
||||
|
||||
// Entity Mutators.
|
||||
int GetEntityX(void) { return _entity.GetX(); }
|
||||
int GetEntityY(void) { return _entity.GetY(); }
|
||||
int GetEntityWidth(void) { return _entity.GetWidth(); }
|
||||
int GetEntityHeight(void) { return _entity.GetHeight(); }
|
||||
|
||||
// ZLevel Mutators.
|
||||
void SetZLevel(int arg) { _zLevel = arg; }
|
||||
int GetZLevel(void) { return _zLevel; }
|
||||
|
||||
// Map Transition Mutators.
|
||||
void SetMapTransitionName(string arg) { _mapTransitionName = arg; }
|
||||
string GetMapTransitionName(void) { return _mapTransitionName; }
|
||||
|
||||
void SetMapTransitionXY(int xArg, int yArg) { _mapTransitionX = xArg, _mapTransitionY = yArg; }
|
||||
int GetMapTransitionX(void) { return _mapTransitionX; }
|
||||
int GetMapTransitionY(void) { return _mapTransitionY; }
|
||||
|
||||
private:
|
||||
MapElement _tile;
|
||||
MapEntityGeneric _entity;
|
||||
|
||||
// -1 is a 'special' tile, the next tile that the player walks
|
||||
// on is the players new zlevel.
|
||||
int _zLevel;
|
||||
|
||||
// If not 'null', switch map when the player walks on this tile.
|
||||
string _mapTransitionName;
|
||||
int _mapTransitionX;
|
||||
int _mapTransitionY;
|
||||
};
|
23
src/libUnuk/Sprite/ApplySurface.cpp
Normal file
23
src/libUnuk/Sprite/ApplySurface.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "ApplySurface.h"
|
||||
|
||||
void ApplySurface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip) {
|
||||
assert(source != NULL);
|
||||
|
||||
SDL_Rect offset;
|
||||
|
||||
offset.x = (Sint16)(x - camera.x);
|
||||
offset.y = (Sint16)(y - camera.y);
|
||||
|
||||
SDL_BlitSurface(source, clip, destination, &offset);
|
||||
}
|
||||
|
||||
void ApplySurfaceLiteral(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip) {
|
||||
assert(source != NULL);
|
||||
|
||||
SDL_Rect offset;
|
||||
|
||||
offset.x = (Sint16)x;
|
||||
offset.y = (Sint16)y;
|
||||
|
||||
SDL_BlitSurface(source, clip, destination, &offset);
|
||||
}
|
16
src/libUnuk/Sprite/ApplySurface.h
Normal file
16
src/libUnuk/Sprite/ApplySurface.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <assert.h>
|
||||
#include "../System/Debug.h"
|
||||
#include "../../Unuk/Globals.h"
|
||||
|
||||
/* Use for objects.
|
||||
* Blit a surface to another surface. An
|
||||
* optioanl clip argument can be given. The surface
|
||||
* will be applied to the destination, taking into
|
||||
* account the position of the camera.
|
||||
*/
|
||||
void ApplySurface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL);
|
||||
|
||||
// This one won't take the camera into account, so we could use it for GUI stuff.
|
||||
void ApplySurfaceLiteral(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL);
|
37
src/libUnuk/Sprite/ImageLoader.cpp
Normal file
37
src/libUnuk/Sprite/ImageLoader.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "ImageLoader.h"
|
||||
|
||||
SDL_Surface* LoadImage(const char* filename) {
|
||||
SDL_Surface* loadedImage = NULL;
|
||||
SDL_Surface* optimizedImage = NULL;
|
||||
|
||||
// Initialize loadedImage with the file.
|
||||
loadedImage = IMG_Load(filename);
|
||||
if(loadedImage != NULL) {
|
||||
// Then copy the image to a surface for us to blit later.
|
||||
optimizedImage = SDL_DisplayFormat(loadedImage);
|
||||
SDL_FreeSurface(loadedImage);
|
||||
return optimizedImage;
|
||||
} else {
|
||||
// Tell us what file is missing and do some stupid error texture thing.
|
||||
Debug::logger->message("ImageLoader: %s cannot be found!");
|
||||
return errorTexture;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* LoadImageAlpha(const char* filename) {
|
||||
SDL_Surface* loadedImage = NULL;
|
||||
SDL_Surface* optimizedImage = NULL;
|
||||
|
||||
// Initialize loadedImage with the file.
|
||||
loadedImage = IMG_Load(filename);
|
||||
if(loadedImage != NULL) {
|
||||
// Then copy the image to a surface and give us an alpha channel.
|
||||
optimizedImage = SDL_DisplayFormatAlpha(loadedImage);
|
||||
SDL_FreeSurface(loadedImage);
|
||||
return optimizedImage;
|
||||
} else {
|
||||
// Tell us what file is missing and do some stupid error texture thing.
|
||||
Debug::logger->message("ImageLoader: %s cannot be found!");
|
||||
return errorTexture;
|
||||
}
|
||||
}
|
8
src/libUnuk/Sprite/ImageLoader.h
Normal file
8
src/libUnuk/Sprite/ImageLoader.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_image.h>
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "../System/Debug.h"
|
||||
|
||||
SDL_Surface* LoadImage(const char* filename);
|
||||
SDL_Surface* LoadImageAlpha(const char* filename);
|
53
src/libUnuk/Sprite/Texture.cpp
Normal file
53
src/libUnuk/Sprite/Texture.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "Texture.h"
|
||||
|
||||
Texture::Texture(void) {
|
||||
_texture = NULL;
|
||||
}
|
||||
|
||||
Texture::~Texture(void) {
|
||||
assert(_texture != NULL);
|
||||
SDL_FreeSurface(_texture);
|
||||
}
|
||||
|
||||
void Texture::SetXY(int xArg, int yArg) {
|
||||
x = xArg;
|
||||
y = yArg;
|
||||
}
|
||||
|
||||
void Texture::Render(void) {
|
||||
ApplySurface(x, y, _texture, screen);
|
||||
}
|
||||
|
||||
void Texture::Render(int xArg, int yArg) {
|
||||
ApplySurface(xArg, yArg, _texture, screen);
|
||||
}
|
||||
|
||||
void Texture::RenderLiteral(void) {
|
||||
ApplySurfaceLiteral(x, y, _texture, screen);
|
||||
}
|
||||
|
||||
void Texture::RenderLiteral(int xArg, int yArg) {
|
||||
ApplySurfaceLiteral(xArg, yArg,_texture, screen);
|
||||
}
|
||||
|
||||
void Texture::Load(const char* filename) {
|
||||
if(_texture != NULL) {
|
||||
// Free the texture.
|
||||
SDL_FreeSurface(_texture);
|
||||
}
|
||||
// Load the texture.
|
||||
_texture = LoadImage(filename);
|
||||
}
|
||||
|
||||
void Texture::LoadAlpha(const char* filename) {
|
||||
if(_texture != NULL) {
|
||||
// Free the texture.
|
||||
SDL_FreeSurface(_texture);
|
||||
}
|
||||
// Load the texture with an alpha channel.
|
||||
_texture = LoadImageAlpha(filename);
|
||||
}
|
||||
|
||||
void Texture::SetAlpha(int alphaArg) {
|
||||
SDL_SetAlpha(_texture, SDL_SRCALPHA, (Uint8)alphaArg);
|
||||
}
|
33
src/libUnuk/Sprite/Texture.h
Normal file
33
src/libUnuk/Sprite/Texture.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "ImageLoader.h"
|
||||
#include "ApplySurface.h"
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
Texture(void);
|
||||
~Texture(void);
|
||||
|
||||
int GetWidth(void) { return _texture->w; }
|
||||
int GetHeight(void) { return _texture->h; }
|
||||
int GetX(void) { return x; }
|
||||
int GetY(void) { return y; }
|
||||
|
||||
void SetXY(int xArg, int yArg);
|
||||
|
||||
void Render(void);
|
||||
void Render(int xArg, int yArg);
|
||||
|
||||
void RenderLiteral(void);
|
||||
void RenderLiteral(int xArg, int yArg);
|
||||
|
||||
void Load(const char* filename);
|
||||
void LoadAlpha(const char* filename);
|
||||
void SetAlpha(int alphaArg);
|
||||
|
||||
protected:
|
||||
int x, y;
|
||||
|
||||
private:
|
||||
SDL_Surface* _texture;
|
||||
};
|
55
src/libUnuk/Sprite/TextureManager.cpp
Normal file
55
src/libUnuk/Sprite/TextureManager.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "TextureManager.h"
|
||||
|
||||
TextureManager::TextureManager(void) {
|
||||
_allocated = 0;
|
||||
}
|
||||
|
||||
TextureManager::~TextureManager(void) {
|
||||
Unload();
|
||||
}
|
||||
|
||||
void TextureManager::Unload(void) {
|
||||
for(int i = 0; i < _allocated; i++) {
|
||||
SDL_FreeSurface(_textures[i].texture);
|
||||
_textures[i].name.clear();
|
||||
}
|
||||
_allocated = 0;
|
||||
}
|
||||
|
||||
SDL_Surface* TextureManager::Add(string filename) {
|
||||
assert(_allocated < TEXTURE_ARR_SIZE - 1);
|
||||
|
||||
// Has the texture been loaded already?
|
||||
for(int i = 0; i < _allocated; i++) {
|
||||
if(_textures[i].name == filename) {
|
||||
return _textures[i].texture;
|
||||
}
|
||||
}
|
||||
// If not, then load it.
|
||||
_textures[_allocated].name = filename;
|
||||
_textures[_allocated].texture = LoadImage(filename.c_str());
|
||||
|
||||
_allocated++;
|
||||
|
||||
return _textures[_allocated - 1].texture;
|
||||
}
|
||||
|
||||
SDL_Surface* TextureManager::AddAlpha(string filename) {
|
||||
assert(_allocated < TEXTURE_ARR_SIZE - 1);
|
||||
|
||||
// Has the texture been loaded already?
|
||||
for(int i = 0; i < _allocated; i++) {
|
||||
if(_textures[i].name == filename) {
|
||||
return _textures[i].texture;
|
||||
}
|
||||
}
|
||||
|
||||
// If not, then load it.
|
||||
|
||||
_textures[_allocated].name = filename;
|
||||
_textures[_allocated].texture = LoadImageAlpha(filename.c_str());
|
||||
|
||||
_allocated++;
|
||||
|
||||
return _textures[_allocated -1].texture;
|
||||
}
|
39
src/libUnuk/Sprite/TextureManager.h
Normal file
39
src/libUnuk/Sprite/TextureManager.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* The Texture Manager will keep a small "Database"
|
||||
* of the name of the texture that is loaded and the
|
||||
* actual texture so we can query it with the filename
|
||||
* and it will return the teture if it is already in memory
|
||||
* or load the tture if it is not.
|
||||
*/
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include "ImageLoader.h"
|
||||
using namespace std;
|
||||
|
||||
class TextureManager {
|
||||
public:
|
||||
TextureManager(void);
|
||||
~TextureManager(void);
|
||||
|
||||
void Unload(void);
|
||||
|
||||
SDL_Surface* Add(string filename);
|
||||
SDL_Surface* AddAlpha(string filename);
|
||||
|
||||
private:
|
||||
// The textureNode will hold the name and the texture.
|
||||
struct textureNode {
|
||||
SDL_Surface* texture;
|
||||
string name;
|
||||
};
|
||||
|
||||
// We should not need more than a hundred..
|
||||
static const int TEXTURE_ARR_SIZE = 100;
|
||||
textureNode _textures[TEXTURE_ARR_SIZE];
|
||||
|
||||
int _allocated;
|
||||
};
|
101
src/libUnuk/System/Debug.cpp
Normal file
101
src/libUnuk/System/Debug.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstdarg>
|
||||
#include <ctime>
|
||||
#include "Debug.h"
|
||||
#include "string"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
// ===================================================================
|
||||
// The Debug log allows us to display ever piece of data that
|
||||
// populates our class components, anything that is loaded, serialized,
|
||||
// de-serialized etc will be printed out to a text file.
|
||||
// (Running our program in a terminal, this debug log will print to it.)
|
||||
// ===================================================================
|
||||
|
||||
Debug *Debug::logger = NULL;
|
||||
|
||||
Debug::Debug(bool logToFile) {
|
||||
time_t timestamp;
|
||||
if(logToFile) {
|
||||
_logFile.open("../Bin/Debug.log", ios::out);
|
||||
if(!logToFile) {
|
||||
// We can not open our log.
|
||||
cerr << "Warning: Can not open Debug.log to write, continueing without logging\n";
|
||||
} else {
|
||||
// Log File is open, let us give it a nice time stamp.
|
||||
timestamp = time(NULL);
|
||||
_logFile << "Log Started: " << ctime(×tamp) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug::~Debug(void) {
|
||||
time_t timestamp;
|
||||
|
||||
// We only need to close the log if it is open.
|
||||
if(_logFile) {
|
||||
// Give it a closing timestamp.
|
||||
timestamp = time(NULL);
|
||||
_logFile << endl << "Log Closed: " << ctime(×tamp) << endl;
|
||||
|
||||
// Close the log file.
|
||||
_logFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void Debug::message(std::string msg) {
|
||||
if(_logFile) {
|
||||
_logFile << msg << endl;
|
||||
}
|
||||
cerr << msg << endl << endl;
|
||||
}
|
||||
|
||||
void Debug::message(const char *msg, ...) {
|
||||
va_list vargList; // This is to handlle the variable arguments
|
||||
|
||||
char outBuf[1024];
|
||||
unsigned short outLen;
|
||||
|
||||
// This takes the arguments and puts them into the character array.
|
||||
va_start(vargList, msg);
|
||||
|
||||
#if defined WIN32
|
||||
outLen = (unsigned short)_vsnprintf(outBuf, sizeof(outBuf), msg, vargList);
|
||||
#else
|
||||
outLen = vsnprintf(outBuf, sizeof(outBuf), msg, vargList);
|
||||
#endif
|
||||
|
||||
va_end(vargList);
|
||||
|
||||
if(outLen >= sizeof(outBuf)) {
|
||||
outLen = sizeof(outBuf);
|
||||
}
|
||||
|
||||
if(_logFile) {
|
||||
_logFile << outBuf << endl;
|
||||
}
|
||||
|
||||
cerr << outBuf << endl;
|
||||
}
|
||||
|
||||
bool Debug::openLog(bool logToFile) {
|
||||
// Make sure the logger has not already been initialized.
|
||||
if(logger != NULL) {
|
||||
logger->message("Warning: Multiple calls to openLog().");
|
||||
return false;
|
||||
}
|
||||
logger = new Debug(logToFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Debug::closeLog(void) {
|
||||
if(logger == NULL) {
|
||||
cerr << "Warning: Call to closeLog() with NULL logger pointer." << endl;
|
||||
return;
|
||||
}
|
||||
delete logger;
|
||||
logger = NULL;
|
||||
}
|
20
src/libUnuk/System/Debug.h
Normal file
20
src/libUnuk/System/Debug.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include <fstream>
|
||||
#include "string"
|
||||
|
||||
class Debug {
|
||||
public:
|
||||
Debug(bool logToFile);
|
||||
~Debug(void);
|
||||
|
||||
// Log an error message.
|
||||
void message(std::string msg);
|
||||
void message(const char *msg, ...);
|
||||
static bool openLog(bool logToFile);
|
||||
static void closeLog(void);
|
||||
|
||||
static Debug *logger;
|
||||
|
||||
private:
|
||||
std::ofstream _logFile;
|
||||
};
|
41
src/libUnuk/System/FPS.cpp
Normal file
41
src/libUnuk/System/FPS.cpp
Normal file
@ -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;
|
||||
}
|
25
src/libUnuk/System/FPS.h
Normal file
25
src/libUnuk/System/FPS.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "../../Unuk/Globals.h"
|
||||
#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;
|
||||
};
|
82
src/libUnuk/System/Input.cpp
Normal file
82
src/libUnuk/System/Input.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include <string.h>
|
||||
#include "Input.h"
|
||||
|
||||
static mouse_t mouse;
|
||||
static keyboard_t keyboard;
|
||||
|
||||
bool _curr_key(int index) {
|
||||
return(keyboard.keys[index] != 0);
|
||||
}
|
||||
|
||||
bool _old_key(int index) {
|
||||
return(keyboard.oldKeys[index] != 0);
|
||||
}
|
||||
|
||||
bool _curr_mouse(int button) {
|
||||
return((mouse.buttons * SDL_BUTTON(button)) != 0);
|
||||
}
|
||||
|
||||
bool _old_mouse(int button) {
|
||||
return((mouse.oldButtons & SDL_BUTTON(button)) != 0);
|
||||
}
|
||||
|
||||
bool CreateInput(void) {
|
||||
memset(&keyboard, 0, sizeof(keyboard_t));
|
||||
memset(&mouse, 0, sizeof(mouse_t));
|
||||
SDL_PumpEvents();
|
||||
SDL_PumpEvents();
|
||||
unsigned char* tempKeys = SDL_GetKeyState(&keyboard.keycount);
|
||||
keyboard.keys = (unsigned char*)malloc(sizeof(char) * keyboard.keycount);
|
||||
keyboard.oldKeys = (unsigned char*)malloc(sizeof(char) * keyboard.keycount);
|
||||
|
||||
memcpy(keyboard.keys, tempKeys, sizeof(char) * keyboard.keycount);
|
||||
mouse.buttons = SDL_GetMouseState(&mouse.dx, &mouse.dy);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UpdateInput(void) {
|
||||
SDL_PumpEvents();
|
||||
keyboard.lastChar = -1;
|
||||
mouse.oldx = mouse.dx;
|
||||
mouse.oldy = mouse.dy;
|
||||
mouse.oldButtons = SDL_GetMouseState(&mouse.dx, &mouse.dy);
|
||||
|
||||
memcpy(keyboard.oldKeys, keyboard.keys, sizeof(char) * keyboard.keycount);
|
||||
|
||||
unsigned char *tmp = SDL_GetKeyState(&keyboard.keycount);
|
||||
memcpy(keyboard.keys, tmp, sizeof(char) * keyboard.keycount);
|
||||
|
||||
keyboard.mods = SDL_GetModState();
|
||||
|
||||
SDL_Event event;
|
||||
while(SDL_PollEvent(&event)) {
|
||||
if(event.type == SDL_KEYDOWN) {
|
||||
keyboard.lastChar = event.key.keysym.sym;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char GetKey(void) {
|
||||
if(keyboard.lastChar != -1)
|
||||
return (char)keyboard.lastChar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int GetX(void) { return mouse.dx; }
|
||||
unsigned int GetY(void) { return mouse.dy; }
|
||||
unsigned int GetOldX(void) { return mouse.oldx; }
|
||||
unsigned int GetOldY(void) { return mouse.oldy; }
|
||||
unsigned int GetMods(void) { return keyboard.mods; }
|
||||
bool KeyDown(int index) { return(_curr_key(index) && !_old_key(index)); }
|
||||
bool KeyStillDown(int index) { return(_curr_key(index) && _old_key(index)); }
|
||||
bool KeyUp(int index) { return(!_curr_key(index) && _old_key(index)); }
|
||||
bool KeyStillUp(int index) { return(!_curr_key(index) && !_old_key(index)); }
|
||||
bool MouseDown(int button) { return(_curr_mouse(button) && !_old_mouse(button)); }
|
||||
bool MouseStillDown(int button) { return(_curr_mouse(button) && _old_mouse(button)); }
|
||||
bool MouseUp(int button) { return(!_curr_mouse(button) && _old_mouse(button)); }
|
||||
bool MouseStillUp(int button) { return(!_curr_mouse(button) && !_old_mouse(button)); }
|
||||
|
||||
void DestroyInput(void) {
|
||||
free(keyboard.keys);
|
||||
free(keyboard.oldKeys);
|
||||
}
|
43
src/libUnuk/System/Input.h
Normal file
43
src/libUnuk/System/Input.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
typedef struct mouse_s {
|
||||
int dx, dy;
|
||||
int oldx, oldy;
|
||||
unsigned int buttons;
|
||||
unsigned int oldButtons;
|
||||
} mouse_t;
|
||||
|
||||
typedef struct keyboard_s {
|
||||
unsigned char *keys;
|
||||
unsigned char *oldKeys;
|
||||
int keycount;
|
||||
int lastChar;
|
||||
unsigned int mods;
|
||||
} keyboard_t;
|
||||
|
||||
typedef struct input_s {
|
||||
mouse_t mouse;
|
||||
keyboard_t keyboard;
|
||||
} input_t;
|
||||
|
||||
bool CreateInput(void);
|
||||
void UpdateInput(void);
|
||||
|
||||
char GetKey(void);
|
||||
|
||||
unsigned int GetX(void);
|
||||
unsigned int GetY(void);
|
||||
unsigned int GetOldX(void);
|
||||
unsigned int GetOldY(void);
|
||||
unsigned int GetMods(void);
|
||||
bool KeyDown(int index);
|
||||
bool KeyStillDown(int index);
|
||||
bool KeyUp(int index);
|
||||
bool KeyStillUp(int index);
|
||||
bool MouseDown(int button);
|
||||
bool MouseStillDown(int button);
|
||||
bool MouseUp(int button);
|
||||
bool MouseStillUp(int button);
|
||||
|
||||
void DestroyInput(void);
|
66
src/libUnuk/System/Rect.cpp
Normal file
66
src/libUnuk/System/Rect.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include "Rect.h"
|
||||
|
||||
Rect::Rect(void) {
|
||||
}
|
||||
|
||||
Rect::~Rect(void) {
|
||||
}
|
||||
|
||||
void Rect::SetXY(int xArg, int yArg) {
|
||||
rect.x = (Sint16)xArg;
|
||||
rect.y = (Sint16)yArg;
|
||||
}
|
||||
|
||||
void Rect::SetWidthHeight(int wArg, int hArg) {
|
||||
rect.w = (Uint16)wArg;
|
||||
rect.h = (Uint16)hArg;
|
||||
}
|
||||
|
||||
void Rect::SetRGB(Uint8 rArg, Uint8 gArg, Uint8 bArg) {
|
||||
r = rArg;
|
||||
g = gArg;
|
||||
b = bArg;
|
||||
}
|
||||
|
||||
void Rect::SetRGB(SDL_Color colour) {
|
||||
r = colour.r;
|
||||
g = colour.g;
|
||||
b = colour.b;
|
||||
}
|
||||
|
||||
void Rect::Draw(void) {
|
||||
SDL_Rect offset;
|
||||
|
||||
offset.x = rect.x - camera.x;
|
||||
offset.y = rect.y - camera.y;
|
||||
offset.w = rect.w;
|
||||
offset.h = rect.h;
|
||||
|
||||
SDL_FillRect(screen, &offset, SDL_MapRGB(screen->format, r, g, b));
|
||||
}
|
||||
|
||||
void Rect::Draw(int xArg, int yArg) {
|
||||
SDL_Rect offset;
|
||||
|
||||
offset.x = (Sint16)(xArg - camera.x);
|
||||
offset.y = (Sint16)(yArg - camera.y);
|
||||
offset.w = (Sint16)rect.w;
|
||||
offset.h = (Sint16)rect.h;
|
||||
|
||||
SDL_FillRect(screen, &offset, SDL_MapRGB(screen->format, r, g, b));
|
||||
}
|
||||
|
||||
void Rect::DrawLiteral(void) {
|
||||
SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
|
||||
}
|
||||
|
||||
void Rect::DrawLiteral(int xArg, int yArg) {
|
||||
SDL_Rect offset;
|
||||
|
||||
offset.x = (Sint16)xArg;
|
||||
offset.y = (Sint16)yArg;
|
||||
offset.w = rect.w;
|
||||
offset.h = rect.h;
|
||||
|
||||
SDL_FillRect(screen, &offset, SDL_MapRGB(screen->format, r, g, b));
|
||||
}
|
35
src/libUnuk/System/Rect.h
Normal file
35
src/libUnuk/System/Rect.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "../Sprite/ApplySurface.h"
|
||||
using namespace std;
|
||||
|
||||
class Rect {
|
||||
public:
|
||||
Rect(void);
|
||||
~Rect(void);
|
||||
|
||||
int GetWidth(void) { return rect.w; }
|
||||
int GetHeight(void) { return rect.h; }
|
||||
int GetX(void) { return rect.x; }
|
||||
int GetY(void) { return rect.y; }
|
||||
|
||||
void SetXY(int xArg, int yArg);
|
||||
void SetWidthHeight(int wArg, int hArg);
|
||||
|
||||
void SetRGB(Uint8 rArg, Uint8 gArg, Uint8 bArg);
|
||||
void SetRGB(SDL_Color);
|
||||
|
||||
void Draw(void);
|
||||
void Draw(int xArg, int yArg);
|
||||
void DrawLiteral(void);
|
||||
void DrawLiteral(int xArg, int yArg);
|
||||
|
||||
protected:
|
||||
Uint8 r;
|
||||
Uint8 g;
|
||||
Uint8 b;
|
||||
|
||||
private:
|
||||
SDL_Rect rect;
|
||||
};
|
54
src/libUnuk/System/Timer.cpp
Normal file
54
src/libUnuk/System/Timer.cpp
Normal file
@ -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();
|
||||
}
|
31
src/libUnuk/System/Timer.h
Normal file
31
src/libUnuk/System/Timer.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include <sstream>
|
||||
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;
|
||||
};
|
120
src/libUnuk/Ui/Button.cpp
Normal file
120
src/libUnuk/Ui/Button.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "Button.h"
|
||||
|
||||
Button::Button(void) {
|
||||
_highlighted = false;
|
||||
_mouseOver = false;
|
||||
}
|
||||
|
||||
Button::~Button(void) {
|
||||
}
|
||||
|
||||
void Button::SetOutRGB(Uint8 r, Uint8 g, Uint8 b) {
|
||||
_button.SetRGB(r, g, b);
|
||||
_mouseOutColour.r = r;
|
||||
_mouseOutColour.g = g;
|
||||
_mouseOutColour.b = b;
|
||||
}
|
||||
|
||||
void Button::SetOutRGB(SDL_Color colour) {
|
||||
_button.SetRGB(colour);
|
||||
_mouseOutColour = colour;
|
||||
}
|
||||
|
||||
void Button::SetOverRGB(Uint8 r, Uint8 g, Uint8 b) {
|
||||
_mouseOverColour.r = r;
|
||||
_mouseOverColour.g = g;
|
||||
_mouseOverColour.b = b;
|
||||
}
|
||||
|
||||
void Button::SetOverRGB(SDL_Color colour) {
|
||||
_mouseOverColour = colour;
|
||||
}
|
||||
|
||||
void Button::SetHighlightRGB(Uint8 r, Uint8 g, Uint8 b) {
|
||||
_highlightColour.r = r;
|
||||
_highlightColour.g = g;
|
||||
_highlightColour.b = b;
|
||||
}
|
||||
|
||||
void Button::SetHighlightRGB(SDL_Color colour) {
|
||||
_highlightColour = colour;
|
||||
}
|
||||
|
||||
void Button::SetXY(int xArg, int yArg) {
|
||||
x = xArg;
|
||||
y = yArg;
|
||||
_button.SetXY(x, y);
|
||||
|
||||
_text.SetXY(x + 10, y + 10);
|
||||
}
|
||||
|
||||
void Button::SetTextRGB(Uint8 r, Uint8 g, Uint8 b) {
|
||||
_textColour.r = r;
|
||||
_textColour.g = g;
|
||||
_textColour.b = b;
|
||||
|
||||
_text.SetTextBlended(_text.GetText(), small, _textColour);
|
||||
}
|
||||
|
||||
void Button::SetTextRGB(SDL_Color colour) {
|
||||
_textColour = colour;
|
||||
_text.SetTextBlended(_text.GetText(), small, colour);
|
||||
}
|
||||
|
||||
void Button::SetText(string textArg) {
|
||||
_text.SetTextBlended(textArg, small, _textColour);
|
||||
|
||||
w = _text.GetWidth();
|
||||
h = _text.GetHeight();
|
||||
_button.SetWidthHeight(w + 20, h + 15);
|
||||
}
|
||||
|
||||
bool Button::CheckMouseOver(void) {
|
||||
if(event.motion.x > _button.GetX() && event.motion.x < _button.GetX() + _button.GetWidth()) {
|
||||
if(event.motion.y > _button.GetY() && event.motion.y < _button.GetY() + _button.GetHeight()) {
|
||||
if(!_highlighted) {
|
||||
_button.SetRGB(_mouseOverColour.r, _mouseOverColour.g, _mouseOverColour.b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(!_highlighted) {
|
||||
_button.SetRGB(_mouseOutColour);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Button::SetHighlighted(bool highlighted) {
|
||||
if(_highlighted != highlighted) {
|
||||
if(highlighted) {
|
||||
_button.SetRGB(_highlightColour);
|
||||
} else {
|
||||
if(!_mouseOver) {
|
||||
_button.SetRGB(_mouseOverColour);
|
||||
} else {
|
||||
_button.SetRGB(_textColour);
|
||||
}
|
||||
}
|
||||
}
|
||||
_highlighted = highlighted;
|
||||
}
|
||||
|
||||
void Button::Render(void) {
|
||||
_button.Draw();
|
||||
_text.Render();
|
||||
}
|
||||
|
||||
void Button::Render(int xArg, int yArg) {
|
||||
_button.Draw(xArg, yArg);
|
||||
_text.Render(xArg, yArg);
|
||||
}
|
||||
|
||||
void Button::RenderLiteral(void) {
|
||||
_button.DrawLiteral();
|
||||
_text.RenderLiteral();
|
||||
}
|
||||
|
||||
void Button::RenderLiteral(int xArg, int yArg) {
|
||||
_button.DrawLiteral(xArg, yArg);
|
||||
_text.RenderLiteral(xArg, yArg);
|
||||
}
|
62
src/libUnuk/Ui/Button.h
Normal file
62
src/libUnuk/Ui/Button.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_ttf.h>
|
||||
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "../System/Input.h"
|
||||
#include "../Ui/Text.h"
|
||||
#include "../System/Rect.h"
|
||||
|
||||
class Button {
|
||||
public:
|
||||
Button(void);
|
||||
~Button(void);
|
||||
|
||||
void SetOutRGB(Uint8 r, Uint8 g, Uint8 b);
|
||||
void SetOutRGB(SDL_Color);
|
||||
void SetOverRGB(Uint8 r, Uint8 g, Uint8 b);
|
||||
void SetOverRGB(SDL_Color);
|
||||
|
||||
void SetTextRGB(Uint8 r, Uint8 g, Uint8 b);
|
||||
void SetTextRGB(SDL_Color);
|
||||
void SetText(string textArg);
|
||||
|
||||
void SetHighlightRGB(Uint8 r, Uint8 g, Uint8 b);
|
||||
void SetHighlightRGB(SDL_Color);
|
||||
|
||||
void SetHighlighted(bool highlighted);
|
||||
|
||||
void SetXY(int xArg, int yArg);
|
||||
|
||||
int GetX(void) const { return x; }
|
||||
int GetY(void) const { return y; }
|
||||
int GetWidth(void) const { return w; }
|
||||
int GetHeight(void) const { return h; }
|
||||
|
||||
bool GetHighlighted(void) { return _highlighted; }
|
||||
|
||||
bool CheckMouseOver(void);
|
||||
|
||||
void Render(void);
|
||||
void Render(int xArg, int yArg);
|
||||
void RenderLiteral(void);
|
||||
void RenderLiteral(int xArg, int yArg);
|
||||
|
||||
private:
|
||||
SDL_Color _mouseOutColour;
|
||||
SDL_Color _mouseOverColour;
|
||||
SDL_Color _textColour;
|
||||
SDL_Color _highlightColour;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
Rect _button;
|
||||
Text _text;
|
||||
|
||||
bool _highlighted;
|
||||
|
||||
bool _mouseOver;
|
||||
};
|
101
src/libUnuk/Ui/ButtonGroup.cpp
Normal file
101
src/libUnuk/Ui/ButtonGroup.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include "ButtonGroup.h"
|
||||
|
||||
ButtonGroup::ButtonGroup(void) {
|
||||
_selectedButton = -1;
|
||||
}
|
||||
|
||||
ButtonGroup::~ButtonGroup(void) {
|
||||
for(std::list<Button*>::iterator i = _buttons.begin(); i != _buttons.end(); ++i) {
|
||||
Button* btn = (*i);
|
||||
delete btn;
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonGroup::CheckMouseOverDummy(void) {
|
||||
for(std::list<Button*>::iterator i = _buttons.begin(); i != _buttons.end(); ++i) {
|
||||
(*i)->CheckMouseOver();
|
||||
}
|
||||
}
|
||||
|
||||
int ButtonGroup::CheckMouseOver(void) {
|
||||
int buttonIndex = 0;
|
||||
for(std::list<Button*>::iterator i = _buttons.begin(); i != _buttons.end(); ++i) {
|
||||
if((*i)->CheckMouseOver()) {
|
||||
return buttonIndex;
|
||||
}
|
||||
buttonIndex++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ButtonGroup::RenderLiteral(void) {
|
||||
for(std::list<Button*>::iterator i = _buttons.begin(); i != _buttons.end(); ++i) {
|
||||
(*i)->RenderLiteral();
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonGroup::AddButton(Button* button) {
|
||||
_buttons.push_back(button);
|
||||
}
|
||||
|
||||
void ButtonGroup::RemoveButton(int index) {
|
||||
int buttonsIndex = 0;
|
||||
for(std::list<Button*>::iterator i = _buttons.begin(); i != _buttons.end(); ++i) {
|
||||
if(buttonsIndex == index) {
|
||||
_buttons.erase(i);
|
||||
break;
|
||||
}
|
||||
buttonsIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonGroup::SelectNext(void) {
|
||||
if(_selectedButton == -1) {
|
||||
HighlightNewSelection(0);
|
||||
} else {
|
||||
HighlightNewSelection(_selectedButton + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonGroup::SelectPrevious(void) {
|
||||
if(_selectedButton == -1) {
|
||||
HighlightNewSelection(0);
|
||||
} else {
|
||||
HighlightNewSelection(_selectedButton - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonGroup::SetSelectedButton(int button) {
|
||||
HighlightNewSelection(button);
|
||||
}
|
||||
|
||||
void ButtonGroup::HighlightNewSelection(int newButton) {
|
||||
if(_selectedButton != -1) {
|
||||
// Turn off highlight for currently highlighted button
|
||||
GetButton(_selectedButton)->SetHighlighted(false);
|
||||
}
|
||||
|
||||
_selectedButton = newButton;
|
||||
|
||||
// If < 0 then up was pressed when first index was selected
|
||||
// If >= _buttons.size() then down was pressed when last index was selected
|
||||
if(_selectedButton < 0) {
|
||||
_selectedButton = _buttons.size() - 1;
|
||||
} else if(_selectedButton >= (int)_buttons.size()) {
|
||||
_selectedButton = 0;
|
||||
}
|
||||
|
||||
// Highlight new selection
|
||||
GetButton(_selectedButton)->SetHighlighted(true);
|
||||
}
|
||||
|
||||
Button* ButtonGroup::GetButton(int index) {
|
||||
int buttonsIndex = 0;
|
||||
for(std::list<Button*>::iterator i = _buttons.begin(); i != _buttons.end(); ++i) {
|
||||
if(buttonsIndex == index) {
|
||||
return (*i);
|
||||
}
|
||||
buttonsIndex++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
33
src/libUnuk/Ui/ButtonGroup.h
Normal file
33
src/libUnuk/Ui/ButtonGroup.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
|
||||
#include "../Ui/Button.h"
|
||||
#include "../Engine/MemClass.h"
|
||||
|
||||
class ButtonGroup {
|
||||
public:
|
||||
ButtonGroup(void);
|
||||
~ButtonGroup(void);
|
||||
|
||||
void CheckMouseOverDummy(void);
|
||||
int CheckMouseOver(void);
|
||||
|
||||
void RenderLiteral(void);
|
||||
|
||||
void AddButton(Button* button);
|
||||
void RemoveButton(int index);
|
||||
|
||||
void SelectNext(void);
|
||||
void SelectPrevious(void);
|
||||
|
||||
int GetSelectedButton(void) { return _selectedButton; }
|
||||
void SetSelectedButton(int button);
|
||||
|
||||
Button* GetButton(int index);
|
||||
|
||||
private:
|
||||
void HighlightNewSelection(int newButton);
|
||||
|
||||
std::list<Button*> _buttons;
|
||||
int _selectedButton;
|
||||
};
|
35
src/libUnuk/Ui/ButtonToggle.cpp
Normal file
35
src/libUnuk/Ui/ButtonToggle.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "ButtonToggle.h"
|
||||
|
||||
ButtonToggle::ButtonToggle(void) {
|
||||
|
||||
}
|
||||
|
||||
ButtonToggle::~ButtonToggle(void) {
|
||||
|
||||
}
|
||||
|
||||
void ButtonToggle::SetOverRGB(Uint8 r, Uint8 g, Uint8 b) {
|
||||
Button::SetOverRGB(r, g, b);
|
||||
}
|
||||
|
||||
void ButtonToggle::SetOverRGB(SDL_Color colour) {
|
||||
Button::SetOverRGB(colour);
|
||||
}
|
||||
|
||||
void ButtonToggle::SetOffRGB(Uint8 r, Uint8 g, Uint8 b) {
|
||||
ButtonToggle::SetOutRGB(r, g, b);
|
||||
}
|
||||
|
||||
void ButtonToggle::SetOffRGB(SDL_Color colour) {
|
||||
Button::SetOutRGB(colour);
|
||||
}
|
||||
|
||||
void ButtonToggle::SetOnRGB(Uint8 r, Uint8 g, Uint8 b) {
|
||||
_onColour.r = r;
|
||||
_onColour.g = g;
|
||||
_onColour.b = b;
|
||||
}
|
||||
|
||||
void ButtonToggle::SetOnRGB(SDL_Color colour) {
|
||||
_onColour = colour;
|
||||
}
|
36
src/libUnuk/Ui/ButtonToggle.h
Normal file
36
src/libUnuk/Ui/ButtonToggle.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_ttf.h>
|
||||
|
||||
#include "Button.h"
|
||||
|
||||
class ButtonToggle : protected Button {
|
||||
public:
|
||||
ButtonToggle(void);
|
||||
~ButtonToggle(void);
|
||||
|
||||
void SetOverRGB(Uint8 r, Uint8 g, Uint8 b);
|
||||
void SetOverRGB(SDL_Color);
|
||||
void SetOffRGB(Uint8 r, Uint8 g, Uint8 b);
|
||||
void SetOffRGB(SDL_Color);
|
||||
void SetOnRGB(Uint8 r, Uint8 g, Uint8 b);
|
||||
void SetOnRGB(SDL_Color);
|
||||
|
||||
void SetTextRGB(Uint8 r, Uint8 g, Uint8 b);
|
||||
void SetOnText(string);
|
||||
void SetOffText(string);
|
||||
|
||||
void SetState(bool);
|
||||
bool GetState(void) { return _state; }
|
||||
|
||||
bool CheckMouseOver(void);
|
||||
|
||||
void Render(void);
|
||||
|
||||
private:
|
||||
bool _state;
|
||||
|
||||
SDL_Colour _onColour;
|
||||
|
||||
Text _onText;
|
||||
};
|
11
src/libUnuk/Ui/Font.cpp
Normal file
11
src/libUnuk/Ui/Font.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "Font.h"
|
||||
|
||||
TTF_Font* Font(const char* filename, const int size) {
|
||||
ifstream font(filename);
|
||||
|
||||
if(font.is_open() == false) {
|
||||
Debug::logger->message("Font: %s cannot be found.");
|
||||
exit(-1);
|
||||
}
|
||||
return TTF_OpenFont(filename, size);
|
||||
}
|
8
src/libUnuk/Ui/Font.h
Normal file
8
src/libUnuk/Ui/Font.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL_ttf.h>
|
||||
#include <fstream>
|
||||
#include <assert.h>
|
||||
#include "../System/Debug.h"
|
||||
using namespace std;
|
||||
|
||||
TTF_Font* Font(const char* filename, const int size);
|
99
src/libUnuk/Ui/IngameMenu.cpp
Normal file
99
src/libUnuk/Ui/IngameMenu.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
#include "IngameMenu.h"
|
||||
|
||||
IngameMenu::IngameMenu(void) {
|
||||
_active = false;
|
||||
|
||||
Button* btnResume = new Button();
|
||||
btnResume->SetOutRGB(200, 200, 200);
|
||||
btnResume->SetOverRGB(255, 255, 255);
|
||||
btnResume->SetTextRGB(0, 0, 0);
|
||||
btnResume->SetText("Resume Game");
|
||||
btnResume->SetHighlightRGB(255, 128, 0);
|
||||
btnResume->SetHighlighted(false);
|
||||
btnResume->SetXY(SCREEN_WIDTH / 2 - btnResume->GetWidth() / 2, 50);
|
||||
|
||||
Button* btnSaveGame = new Button();
|
||||
btnSaveGame->SetOutRGB(200, 200, 200);
|
||||
btnSaveGame->SetOverRGB(255, 255, 255);
|
||||
btnSaveGame->SetTextRGB(0, 0, 0);
|
||||
btnSaveGame->SetText("SaveGame");
|
||||
btnSaveGame->SetHighlightRGB(255, 128, 0);
|
||||
btnSaveGame->SetHighlighted(false);
|
||||
btnSaveGame->SetXY(SCREEN_WIDTH / 2 - btnSaveGame->GetWidth() / 2, 100);
|
||||
|
||||
Button* btnLoadGame = new Button();
|
||||
btnLoadGame->SetOutRGB(200, 200, 200);
|
||||
btnLoadGame->SetOverRGB(255, 255, 255);
|
||||
btnLoadGame->SetTextRGB(0, 0, 0);
|
||||
btnLoadGame->SetText("LoadGame");
|
||||
btnLoadGame->SetHighlightRGB(255, 128, 0);
|
||||
btnLoadGame->SetHighlighted(false);
|
||||
btnLoadGame->SetXY(SCREEN_WIDTH / 2 - btnLoadGame->GetWidth() / 2, 150);
|
||||
|
||||
Button* btnOptions = new Button();
|
||||
btnOptions->SetOutRGB(200, 200, 200);
|
||||
btnOptions->SetOverRGB(255, 255, 255);
|
||||
btnOptions->SetTextRGB(0, 0, 0);
|
||||
btnOptions->SetText("Options");
|
||||
btnOptions->SetHighlightRGB(255, 128, 0);
|
||||
btnOptions->SetHighlighted(false);
|
||||
btnOptions->SetXY(SCREEN_WIDTH / 2 - btnOptions->GetWidth() / 2, 200);
|
||||
|
||||
Button* btnExitToMenu = new Button();
|
||||
btnExitToMenu->SetOutRGB(200, 200, 200);
|
||||
btnExitToMenu->SetOverRGB(255, 255, 255);
|
||||
btnExitToMenu->SetTextRGB(0, 0, 0);
|
||||
btnExitToMenu->SetText("Exit To Main Menu");
|
||||
btnExitToMenu->SetHighlightRGB(255, 128, 0);
|
||||
btnExitToMenu->SetHighlighted(false);
|
||||
btnExitToMenu->SetXY(SCREEN_WIDTH / 2 - btnExitToMenu->GetWidth() / 2, 250);
|
||||
|
||||
_buttons.AddButton(btnResume);
|
||||
_buttons.AddButton(btnSaveGame);
|
||||
_buttons.AddButton(btnLoadGame);
|
||||
_buttons.AddButton(btnOptions);
|
||||
_buttons.AddButton(btnExitToMenu);
|
||||
}
|
||||
|
||||
IngameMenu::~IngameMenu(void) {
|
||||
}
|
||||
|
||||
ingameMenuNavVal_t IngameMenu::HandleInput(void) {
|
||||
while(SDL_PollEvent(&event)) {
|
||||
_buttons.CheckMouseOverDummy();
|
||||
|
||||
if(event.key.type == SDL_KEYDOWN) {
|
||||
if(event.key.keysym.sym == SDLK_ESCAPE) {
|
||||
return ingameMenuResume;
|
||||
} else if(event.key.keysym.sym == SDLK_DOWN) {
|
||||
_buttons.SelectNext();
|
||||
} else if(event.key.keysym.sym == SDLK_UP) {
|
||||
_buttons.SelectPrevious();
|
||||
} else if(event.key.keysym.sym == SDLK_RETURN) {
|
||||
switch(_buttons.GetSelectedButton()) {
|
||||
case 0: return ingameMenuResume;
|
||||
case 1: return ingameMenuSaveGame;
|
||||
case 2: return ingameMenuLoadGame;
|
||||
case 3: return ingameMenuOptions;
|
||||
case 4: return ingameMenuMainMenu;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(event.type == SDL_MOUSEBUTTONUP) {
|
||||
if(event.button.button == SDL_BUTTON_LEFT) {
|
||||
switch(_buttons.CheckMouseOver()) {
|
||||
case 0: return ingameMenuResume;
|
||||
case 1: return ingameMenuSaveGame;
|
||||
case 2: return ingameMenuLoadGame;
|
||||
case 3: return ingameMenuOptions;
|
||||
case 4: return ingameMenuMainMenu;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ingameMenuNothing;
|
||||
}
|
||||
|
||||
void IngameMenu::Render(void) {
|
||||
_buttons.RenderLiteral();
|
||||
}
|
32
src/libUnuk/Ui/IngameMenu.h
Normal file
32
src/libUnuk/Ui/IngameMenu.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "../../Unuk/Constants.h"
|
||||
#include "ButtonGroup.h"
|
||||
#include "ButtonToggle.h"
|
||||
|
||||
enum ingameMenuNavVal_t {
|
||||
ingameMenuNothing,
|
||||
ingameMenuResume,
|
||||
ingameMenuSaveGame,
|
||||
ingameMenuLoadGame,
|
||||
ingameMenuOptions,
|
||||
ingameMenuMainMenu
|
||||
};
|
||||
|
||||
class IngameMenu {
|
||||
public:
|
||||
IngameMenu(void);
|
||||
~IngameMenu(void);
|
||||
|
||||
ingameMenuNavVal_t HandleInput(void);
|
||||
void Render(void);
|
||||
|
||||
void SetStatus(bool arg) { _active = arg; }
|
||||
bool GetStatus(void) { return _active; }
|
||||
|
||||
private:
|
||||
bool _active;
|
||||
|
||||
ButtonGroup _buttons;
|
||||
};
|
171
src/libUnuk/Ui/MainMenu.cpp
Normal file
171
src/libUnuk/Ui/MainMenu.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
#include "MainMenu.h"
|
||||
|
||||
MainMenu::MainMenu(void) {
|
||||
Button* btnNewGame = new Button();
|
||||
btnNewGame->SetOutRGB(200, 200, 200);
|
||||
btnNewGame->SetOverRGB(255, 255, 255);
|
||||
btnNewGame->SetTextRGB(0, 0, 0);
|
||||
btnNewGame->SetText("New Game");
|
||||
btnNewGame->SetXY(100, 150);
|
||||
btnNewGame->SetHighlightRGB(255, 128, 0);
|
||||
btnNewGame->SetHighlighted(false);
|
||||
|
||||
Button* btnLoadGame = new Button();
|
||||
btnLoadGame->SetOutRGB(200, 200, 200);
|
||||
btnLoadGame->SetOverRGB(255, 255, 255);
|
||||
btnLoadGame->SetTextRGB(0, 0, 0);
|
||||
btnLoadGame->SetText("Load Game");
|
||||
btnLoadGame->SetHighlightRGB(255, 128, 0);
|
||||
btnLoadGame->SetHighlighted(false);
|
||||
btnLoadGame->SetXY(100, 200);
|
||||
|
||||
Button* btnOptions = new Button();
|
||||
btnOptions->SetOutRGB(200, 200, 200);
|
||||
btnOptions->SetOverRGB(255, 255, 255);
|
||||
btnOptions->SetTextRGB(0, 0, 0);
|
||||
btnOptions->SetText("Options");
|
||||
btnOptions->SetHighlightRGB(255, 128, 0);
|
||||
btnOptions->SetHighlighted(false);
|
||||
btnOptions->SetXY(100, 250);
|
||||
|
||||
Button* btnExit = new Button();
|
||||
btnExit->SetOutRGB(200, 200, 200);
|
||||
btnExit->SetOverRGB(255, 255, 255);
|
||||
btnExit->SetTextRGB(0, 0, 0);
|
||||
btnExit->SetText("Exit");
|
||||
btnExit->SetHighlightRGB(255, 128, 0);
|
||||
btnExit->SetHighlighted(false);
|
||||
btnExit->SetXY(100, 300);
|
||||
|
||||
grpMain.AddButton(btnNewGame);
|
||||
grpMain.AddButton(btnLoadGame);
|
||||
grpMain.AddButton(btnOptions);
|
||||
grpMain.AddButton(btnExit);
|
||||
|
||||
btnNewGameActive = false;
|
||||
|
||||
lblNewGame.SetXY(275, 160);
|
||||
lblNewGame.SetTextBlended("This will delete your current game, are you sure?", vsmall, 0, 0, 0);
|
||||
|
||||
rectNewGame.SetRGB(200, 200, 200);
|
||||
rectNewGame.SetXY(250, 150);
|
||||
rectNewGame.SetWidthHeight(lblNewGame.GetWidth() + 50, 90);
|
||||
|
||||
lblMenu.SetXY(100, 75);
|
||||
lblMenu.SetTextBlended("Unuk", vlarge, 0, 0, 0);
|
||||
|
||||
Button* btnNewGameYes = new Button();
|
||||
btnNewGameYes->SetOutRGB(20, 150, 20);
|
||||
btnNewGameYes->SetOverRGB(20, 255, 20);
|
||||
btnNewGameYes->SetTextRGB(0, 0, 0);
|
||||
btnNewGameYes->SetText("Yes");
|
||||
btnNewGameYes->SetHighlightRGB(255, 128, 0);
|
||||
btnNewGameYes->SetHighlighted(false);
|
||||
btnNewGameYes->SetXY(rectNewGame.GetX() + rectNewGame.GetWidth() / 2 - 40 - btnNewGameYes->GetWidth(), 190);
|
||||
|
||||
Button* btnNewGameNo = new Button();
|
||||
btnNewGameNo->SetOutRGB(150, 20, 20);
|
||||
btnNewGameNo->SetOverRGB(255, 20, 20);
|
||||
btnNewGameNo->SetTextRGB(0, 0, 0);
|
||||
btnNewGameNo->SetText("No");
|
||||
btnNewGameNo->SetHighlightRGB(255, 128, 0);
|
||||
btnNewGameNo->SetHighlighted(false);
|
||||
btnNewGameNo->SetXY(rectNewGame.GetX() + rectNewGame.GetWidth() / 2 + 40 - btnNewGameNo->GetWidth(), 190);
|
||||
|
||||
grpNewGame.AddButton(btnNewGameYes);
|
||||
grpNewGame.AddButton(btnNewGameNo);
|
||||
|
||||
//m_background.Load("MainMenu");
|
||||
|
||||
camera.x = 0;
|
||||
camera.y = 0;
|
||||
}
|
||||
|
||||
MainMenu::~MainMenu(void) {
|
||||
|
||||
}
|
||||
|
||||
mainMenuNavVal_t MainMenu::Run(void) {
|
||||
FPS fpsLimiter(20);
|
||||
|
||||
bool running = true;
|
||||
while(running) {
|
||||
Render();
|
||||
SDL_Flip(screen);
|
||||
|
||||
while(SDL_PollEvent(&event)) {
|
||||
grpMain.CheckMouseOverDummy();
|
||||
|
||||
if(btnNewGameActive) {
|
||||
grpNewGame.CheckMouseOverDummy();
|
||||
}
|
||||
|
||||
if(event.key.type == SDL_KEYDOWN) {
|
||||
if(event.key.keysym.sym == SDLK_DOWN) {
|
||||
if(btnNewGameActive) {
|
||||
grpNewGame.SelectNext();
|
||||
} else {
|
||||
grpMain.SelectNext();
|
||||
}
|
||||
} else if(event.key.keysym.sym == SDLK_UP) {
|
||||
if(btnNewGameActive) {
|
||||
grpNewGame.SelectPrevious();
|
||||
} else {
|
||||
grpMain.SelectPrevious();
|
||||
}
|
||||
} else if(event.key.keysym.sym == SDLK_RETURN) {
|
||||
if(btnNewGameActive) {
|
||||
switch(grpNewGame.GetSelectedButton()) {
|
||||
case 0: return mainMenuNewGame; break;
|
||||
case 1: btnNewGameActive = false; break;
|
||||
}
|
||||
} else {
|
||||
switch(grpMain.GetSelectedButton()) {
|
||||
case 0: btnNewGameActive = !btnNewGameActive; break;
|
||||
case 1: return mainMenuLoadGame;
|
||||
case 2: return mainMenuOptions;
|
||||
case 3: return mainMenuExitGame;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(event.type == SDL_MOUSEBUTTONUP) {
|
||||
if(event.button.button == SDL_BUTTON_LEFT) {
|
||||
switch(grpMain.CheckMouseOver()) {
|
||||
case 0: btnNewGameActive = !btnNewGameActive; break;
|
||||
case 1: return mainMenuLoadGame;
|
||||
case 2: return mainMenuOptions;
|
||||
case 3: return mainMenuExitGame;
|
||||
}
|
||||
|
||||
if(btnNewGameActive) {
|
||||
switch(grpNewGame.CheckMouseOver()) {
|
||||
case 0: return mainMenuNewGame; break;
|
||||
case 1: btnNewGameActive = false; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(event.type == SDL_QUIT) {
|
||||
return mainMenuExitGame;
|
||||
}
|
||||
}
|
||||
|
||||
fpsLimiter.LimitFPS();
|
||||
}
|
||||
return mainMenuExitGame;
|
||||
}
|
||||
|
||||
void MainMenu::Render(void) {
|
||||
//m_background.Render();
|
||||
|
||||
lblMenu.Render();
|
||||
|
||||
grpMain.RenderLiteral();
|
||||
|
||||
if(btnNewGameActive) {
|
||||
rectNewGame.Draw();
|
||||
lblNewGame.Render();
|
||||
grpNewGame.RenderLiteral();
|
||||
}
|
||||
}
|
37
src/libUnuk/Ui/MainMenu.h
Normal file
37
src/libUnuk/Ui/MainMenu.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../Unuk/Constants.h"
|
||||
#include "../System/FPS.h"
|
||||
#include "../Ui/ButtonGroup.h"
|
||||
#include "../Map/Map.h"
|
||||
#include "../System/Rect.h"
|
||||
#include "../Ui/Text.h"
|
||||
|
||||
enum mainMenuNavVal_t {
|
||||
mainMenuNewGame,
|
||||
mainMenuLoadGame,
|
||||
mainMenuOptions,
|
||||
mainMenuExitGame
|
||||
};
|
||||
|
||||
class MainMenu {
|
||||
public:
|
||||
MainMenu(void);
|
||||
~MainMenu(void);
|
||||
|
||||
mainMenuNavVal_t Run(void);
|
||||
|
||||
private:
|
||||
void Render(void);
|
||||
|
||||
Map _background;
|
||||
|
||||
Text lblMenu;
|
||||
|
||||
ButtonGroup grpMain;
|
||||
|
||||
bool btnNewGameActive;
|
||||
Rect rectNewGame;
|
||||
Text lblNewGame;
|
||||
ButtonGroup grpNewGame;
|
||||
};
|
269
src/libUnuk/Ui/Text.cpp
Normal file
269
src/libUnuk/Ui/Text.cpp
Normal file
@ -0,0 +1,269 @@
|
||||
#include "Text.h"
|
||||
|
||||
TTF_Font* Text::vSmallFont = NULL;
|
||||
TTF_Font* Text::smallFont = NULL;
|
||||
TTF_Font* Text::mediumFont = NULL;
|
||||
TTF_Font* Text::largeFont = NULL;
|
||||
TTF_Font* Text::vLargeFont = NULL;
|
||||
|
||||
const static int lineSpacing = 3;
|
||||
|
||||
Text::Text(void) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = 0;
|
||||
h = 0;
|
||||
lineWidth=50;
|
||||
}
|
||||
|
||||
Text::~Text(void) {
|
||||
if(!_lines.empty()) {
|
||||
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
|
||||
SDL_FreeSurface(*it);
|
||||
}
|
||||
_lines.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Text::LoadFonts(void) {
|
||||
// Load the fonts if they are not already in memory.
|
||||
assert(vSmallFont == NULL);
|
||||
assert(smallFont == NULL);
|
||||
assert(mediumFont == NULL);
|
||||
assert(largeFont == NULL);
|
||||
assert(vLargeFont == NULL);
|
||||
|
||||
vSmallFont = Font("../Data/Media/Fonts/Enigma_2.ttf", 16);
|
||||
smallFont = Font("../Data/Media/Fonts/Enigma_2.ttf", 23);
|
||||
mediumFont = Font("../Data/Media/Fonts/Enigma_2.ttf", 27);
|
||||
largeFont = Font("../Data/Media/Fonts/Enigma_2.ttf", 32);
|
||||
vLargeFont = Font("../Data/Media/Fonts/Enigma_2.ttf", 48);
|
||||
}
|
||||
|
||||
void Text::FreeFonts(void) {
|
||||
// If the fonts are loaded, then free them.
|
||||
assert(vSmallFont != NULL);
|
||||
assert(smallFont != NULL);
|
||||
assert(mediumFont != NULL);
|
||||
assert(largeFont != NULL);
|
||||
assert(vLargeFont != NULL);
|
||||
|
||||
TTF_CloseFont(vSmallFont);
|
||||
TTF_CloseFont(smallFont);
|
||||
TTF_CloseFont(mediumFont);
|
||||
TTF_CloseFont(largeFont);
|
||||
TTF_CloseFont(vLargeFont);
|
||||
}
|
||||
|
||||
void Text::SetXY(int xArg, int yArg) {
|
||||
x = xArg;
|
||||
y = yArg;
|
||||
}
|
||||
|
||||
int Text::SetTextBlended(string textArg, textSizes_t size, SDL_Color colour,bool wordWrap) {
|
||||
_textContents = textArg;
|
||||
|
||||
if(!_lines.empty()) {
|
||||
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
|
||||
SDL_FreeSurface(*it);
|
||||
}
|
||||
_lines.clear();
|
||||
}
|
||||
|
||||
TTF_Font* font = NULL;
|
||||
if(size == vsmall) {
|
||||
font = vSmallFont;
|
||||
} else if(size == small) {
|
||||
font = smallFont;
|
||||
} else if(size == medium) {
|
||||
font = mediumFont;
|
||||
} else if(size == large) {
|
||||
font = largeFont;
|
||||
} else {
|
||||
font = vLargeFont;
|
||||
}
|
||||
|
||||
std::string finalTextContents = textArg;
|
||||
|
||||
if(wordWrap) {
|
||||
finalTextContents = DoWordWrap(font, finalTextContents);
|
||||
}
|
||||
|
||||
std::list<std::string> lines;
|
||||
std::string line;
|
||||
for(int i = 0; i < (int)finalTextContents.size(); i++) {
|
||||
char c = finalTextContents.at(i);
|
||||
if(c == '\n') {
|
||||
lines.push_back(line);
|
||||
line.clear();
|
||||
} else {
|
||||
line += c;
|
||||
}
|
||||
}
|
||||
if (!line.empty()) {
|
||||
lines.push_back(line);
|
||||
}
|
||||
|
||||
for(std::list<std::string>::iterator it = lines.begin(); it != lines.end(); ++it) {
|
||||
SDL_Surface* lineSurf = TTF_RenderText_Blended(font, it->c_str(), colour);
|
||||
|
||||
int linePixelWidth;
|
||||
int linePixelHeight;
|
||||
TTF_SizeText(font, it->c_str(), &linePixelWidth, &linePixelHeight);
|
||||
|
||||
if(linePixelWidth > w) {
|
||||
w = linePixelWidth;
|
||||
}
|
||||
|
||||
h += linePixelHeight + lineSpacing;
|
||||
|
||||
_lines.push_back(lineSurf);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Text::SetTextBlended(string textArg, textSizes_t size, Uint8 r, Uint8 g, Uint8 b, bool wordWrap) {
|
||||
SDL_Color f = { r, g, b };
|
||||
return SetTextBlended(textArg, size, f, wordWrap);
|
||||
}
|
||||
|
||||
int Text::SetTextShaded(string textArg, textSizes_t size, SDL_Color colour, SDL_Color bgColour, bool wordWrap) {
|
||||
_textContents = textArg;
|
||||
|
||||
if(!_lines.empty()) {
|
||||
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
|
||||
SDL_FreeSurface(*it);
|
||||
}
|
||||
_lines.clear();
|
||||
}
|
||||
|
||||
TTF_Font* font = NULL;
|
||||
if(size == vsmall) {
|
||||
font = vSmallFont;
|
||||
} else if(size == small) {
|
||||
font = smallFont;
|
||||
} else if(size == medium) {
|
||||
font = mediumFont;
|
||||
} else if(size == large) {
|
||||
font = largeFont;
|
||||
} else {
|
||||
font = vLargeFont;
|
||||
}
|
||||
|
||||
std::string finalTextContents = textArg;
|
||||
|
||||
if(wordWrap) {
|
||||
finalTextContents = DoWordWrap(font, finalTextContents);
|
||||
}
|
||||
|
||||
std::list<std::string> lines;
|
||||
std::string line;
|
||||
for(int i = 0; i < (int)finalTextContents.size(); i++) {
|
||||
char c = finalTextContents.at(i);
|
||||
if(c == '\n') {
|
||||
lines.push_back(line);
|
||||
line.clear();
|
||||
} else {
|
||||
line += c;
|
||||
}
|
||||
}
|
||||
if (!line.empty()) {
|
||||
lines.push_back(line);
|
||||
}
|
||||
|
||||
for(std::list<std::string>::iterator it = lines.begin(); it != lines.end(); ++it) {
|
||||
SDL_Surface* lineSurf = TTF_RenderText_Shaded(font, it->c_str(), colour, bgColour);
|
||||
|
||||
int linePixelWidth;
|
||||
int linePixelHeight;
|
||||
TTF_SizeText(font, it->c_str(), &linePixelWidth, &linePixelHeight);
|
||||
|
||||
if(linePixelWidth > w) {
|
||||
w = linePixelWidth;
|
||||
}
|
||||
|
||||
h += linePixelHeight + lineSpacing;
|
||||
|
||||
_lines.push_back(lineSurf);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Text::SetTextShaded(string textArg, textSizes_t size, Uint8 rF, Uint8 gF, Uint8 bF, Uint8 rB, Uint8 gB, Uint8 bB, bool wordWrap) {
|
||||
SDL_Color f = { rF, gF, bF };
|
||||
SDL_Color b = { rB, gB, bB };
|
||||
return SetTextShaded(textArg, size, f, b, wordWrap);
|
||||
}
|
||||
|
||||
void Text::Render(void) {
|
||||
int yOffset = 0;
|
||||
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
|
||||
SDL_Surface* lineSurf = *it;
|
||||
ApplySurface(x, y + yOffset, lineSurf, screen);
|
||||
yOffset += lineSurf->h + lineSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::Render(int xArg, int yArg) {
|
||||
int yOffset = 0;
|
||||
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
|
||||
SDL_Surface* lineSurf = *it;
|
||||
ApplySurface(x + xArg, y + yArg + yOffset, lineSurf, screen);
|
||||
yOffset += lineSurf->h + lineSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::RenderLiteral(void) {
|
||||
int yOffset = 0;
|
||||
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
|
||||
SDL_Surface* lineSurf = *it;
|
||||
ApplySurfaceLiteral(x, y + yOffset, lineSurf, screen);
|
||||
yOffset += lineSurf->h + lineSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::RenderLiteral(int xArg, int yArg) {
|
||||
int yOffset = 0;
|
||||
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
|
||||
SDL_Surface* lineSurf = *it;
|
||||
ApplySurfaceLiteral(x + xArg, y + yArg + yOffset, lineSurf, screen);
|
||||
yOffset += lineSurf->h + lineSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Text::DoWordWrap(TTF_Font* fontArg, const std::string& textArg) {
|
||||
int leftSpace = lineWidth;
|
||||
|
||||
char* tokenizedText = strdup(textArg.c_str());
|
||||
char* tokenizedTextOrigin = tokenizedText;
|
||||
|
||||
std::string wrappedText(textArg);
|
||||
int offsetInWrappedText = 0;
|
||||
|
||||
int spaceWidth;
|
||||
TTF_SizeText(fontArg, " ", &spaceWidth, NULL);
|
||||
|
||||
char* word = strtok(tokenizedText, " ");
|
||||
|
||||
while(word) {
|
||||
int wordWidth;
|
||||
TTF_SizeText(fontArg, word, &wordWidth, NULL);
|
||||
|
||||
if ((wordWidth + spaceWidth) > leftSpace) {
|
||||
wrappedText.insert((word - tokenizedTextOrigin) + offsetInWrappedText, "\n");
|
||||
offsetInWrappedText++;
|
||||
|
||||
leftSpace = lineWidth - wordWidth;
|
||||
} else {
|
||||
leftSpace -= wordWidth + spaceWidth;
|
||||
}
|
||||
|
||||
word = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
// delete[] tokenizedText;
|
||||
|
||||
return wrappedText;
|
||||
}
|
62
src/libUnuk/Ui/Text.h
Normal file
62
src/libUnuk/Ui/Text.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_ttf.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include "../../Unuk/Globals.h"
|
||||
#include "../Sprite/ApplySurface.h"
|
||||
#include "../Ui/Font.h"
|
||||
#include "../System/Debug.h"
|
||||
using namespace std;
|
||||
|
||||
enum textSizes_t { vsmall, small, medium, large, vlarge };
|
||||
|
||||
class Text {
|
||||
public:
|
||||
Text(void);
|
||||
~Text(void);
|
||||
|
||||
static void LoadFonts(void);
|
||||
static void FreeFonts(void);
|
||||
|
||||
int GetWidth(void) { return w; }
|
||||
int GetHeight(void) { return h; }
|
||||
int GetX(void) { return x; }
|
||||
int GetY(void) { return y; }
|
||||
|
||||
SDL_Color GetColour(void) { return _textColour; }
|
||||
|
||||
void SetXY(int xArg, int yArg);
|
||||
|
||||
int GetLineWidth() { return lineWidth; }
|
||||
void SetLineWidth(int lineWidthArg) { lineWidth = lineWidthArg; }
|
||||
|
||||
int SetTextBlended(string textArg, textSizes_t size, SDL_Color, bool wordWrap=false);
|
||||
int SetTextBlended(string textArg, textSizes_t size, Uint8 r, Uint8 g, Uint8 b, bool wordWrap=false);
|
||||
int SetTextShaded(string textArg, textSizes_t size, SDL_Color, SDL_Color, bool wordWrap=false);
|
||||
int SetTextShaded(string textArg, textSizes_t size, Uint8 rF, Uint8 gF, Uint8 bF, Uint8 rB, Uint8 gB, Uint8 bB, bool wordWrap=false);
|
||||
|
||||
string GetText(void) { return _textContents; }
|
||||
|
||||
void Render(void);
|
||||
void Render(int xArg, int yArg);
|
||||
void RenderLiteral(void);
|
||||
void RenderLiteral(int xArg, int yArg);
|
||||
|
||||
private:
|
||||
int x, y, w, h;
|
||||
int lineWidth;
|
||||
|
||||
string _textContents;
|
||||
SDL_Color _textColour;
|
||||
std::list<SDL_Surface*> _lines;
|
||||
|
||||
std::string DoWordWrap(TTF_Font* fontArg, const std::string& textArg);
|
||||
|
||||
static TTF_Font* vSmallFont;
|
||||
static TTF_Font* smallFont;
|
||||
static TTF_Font* mediumFont;
|
||||
static TTF_Font* largeFont;
|
||||
static TTF_Font* vLargeFont;
|
||||
};
|
Loading…
Reference in New Issue
Block a user