Browse Source

Moved some useful code from Horizon into Base; made readme look prettier

master
Macoy Madson 5 years ago
parent
commit
0aa567d928
11 changed files with 873 additions and 25 deletions
  1. +2
    -0
      .gitignore
  2. +17
    -23
      README.md
  3. +5
    -0
      dataStructures/pool.cpp
  4. +157
    -0
      dataStructures/pool.hpp
  5. +5
    -0
      dataStructures/quadTree.cpp
  6. +354
    -0
      dataStructures/quadTree.hpp
  7. +97
    -0
      graphics/imageManager.cpp
  8. +60
    -0
      graphics/imageManager.hpp
  9. +66
    -0
      input/inputState.cpp
  10. +85
    -0
      input/inputState.hpp
  11. +25
    -2
      makefile

+ 2
- 0
.gitignore View File

@@ -28,3 +28,5 @@
*.app

LOCAL*
~*
*~

+ 17
- 23
README.md View File

@@ -1,49 +1,43 @@
# base2.0
# Base2.0
A simple game library and abstraction layer for SFML 2.2

------------------
Base
------------------

Setup
-----
You need SFML 2.0 installed if you have base2.0, or SFML 1.6 if you have base.

It's then really easy from there; just
make
make tools
sudo make install
sudo make installTools
It's then really easy from there; just
make
make tools
sudo make install
sudo make installTools

If you want to clean up:
sudo make clean
sudo make cleanTools
sudo make clean
sudo make cleanTools

Installing the library will result in the following:
/usr/include/base2.0 will contain all of the header files. To use them:
* /usr/include/base2.0 will contain all of the header files. To use them:
#include <base2.0/module/module.hpp>

/usr/lib will contain libbase2.0.a or libbase.a . Use these when linking like so:
* /usr/lib will contain libbase2.0.a or libbase.a . Use these when linking like so:
g++ -o "myProj" myProj.o -lbase2.0 [or -lbase] -lsfml-audio -lsfml-graphics -lsfml-window -lsfml-system

The Tile Map Editor (tileEditor) binary will be added to /usr/bin
"tle.desktop" will be added to /usr/share/applications, which adds the Tile Map Editor to the Ubuntu Dash
* The Tile Map Editor (tileEditor) binary will be added to /usr/bin
* "tle.desktop" will be added to /usr/share/applications, which adds the Tile Map Editor to the Ubuntu Dash

Cleaning will undo all of these changes.
Basic Use (installed)
------
#include <base[or base2.0]/module/module.hpp>
#include <base[or base2.0]/module/module.hpp>

To link:
g++ -o "myProj" myProj.o -lbase [or -lbase2.0] -lsfml-audio -lsfml-graphics -lsfml-window -lsfml-system
g++ -o "myProj" myProj.o -lbase [or -lbase2.0] -lsfml-audio -lsfml-graphics -lsfml-window -lsfml-system

Basic Use (not installed)
------
#include "/path/to/base/module/module.hpp"
#include "/path/to/base/module/module.hpp"

To link:
g++ -o "myProj" myProj.o "/path/to/base/lib/base.a" -lsfml-audio -lsfml-graphics -lsfml-window -lsfml-system
g++ -o "myProj" myProj.o "/path/to/base/lib/base.a" -lsfml-audio -lsfml-graphics -lsfml-window -lsfml-system

About
------


+ 5
- 0
dataStructures/pool.cpp View File

@@ -0,0 +1,5 @@
#ifndef POOL_CPP
#define POOL_CPP
#include "pool.hpp"

#endif

+ 157
- 0
dataStructures/pool.hpp View File

@@ -0,0 +1,157 @@
#ifndef POOL_HPP
#define POOL_HPP
#include <stdlib.h>
#include <vector>
#include <iostream>

/* --Pool--
* Pool holds any data. It initializes the requested amount of data on construction.
* Any subsequent calls to getNewData() and removeData() cost very little
* because no more memory is allocated or freed. This provides significant
* speed improvements.
*
* It uses a doubly linked list for faster iteration through the active data
* and a singly linked list for iteration through free/inactive data.
*
* Vector is used to store the data due to its resize function, which allows
* the pool's size to be set on initialization. The pool cannot be resized
* after initialization because vector must move all data to get one complete
* block.
*
* Note: You must compile with -std=c++11 if you want your data type's
* constructors to be called.
*
* TODO: Need to construct inUse list to be in order (better locality)!
* */

//Generic data container. Holds the requested data as well as pointers to the next
//free data (if inactive), and the previous and next active/used data (if active)
template<class T>
class PoolData
{
public:
T data;
bool isActive;
PoolData<T>* nextFreeData;
PoolData<T>* nextUsedData;
PoolData<T>* prevUsedData;
};

template<class R>
class Pool
{
private:
std::vector<PoolData<R> > pool; //The pool data, stored in a STL vector
PoolData<R>* firstFreeData; //The head of the free data linked list
PoolData<R>* firstUsedData; //The head of the used data linked list
unsigned int size; //The size of the pool
unsigned int totalActiveData; //The number of active data in the pool
//Prepare the data pointers as a linked list
void resetPool()
{
//Iterate through all data, resetting pointers and isActive status
firstFreeData = &pool[0];
for (unsigned int i = 0; i < size - 1; ++i)
{
PoolData<R>* currentData = &pool[i];
currentData->nextFreeData = &pool[i + 1];
currentData->nextUsedData = NULL;
currentData->prevUsedData = NULL;
currentData->isActive = false;
}
//Last datum needs NULL status to signal end of linked list
PoolData<R>* lastData = &pool[size - 1];
lastData->nextFreeData = NULL;
lastData->nextUsedData = NULL;
lastData->prevUsedData = NULL;
lastData->isActive = false;
}
public:
//Initializes the Pool with newSize elements. Once this constructor
//is called, no more memory is allocated.
Pool(unsigned int newSize)
{
size = newSize;
totalActiveData = 0;
firstFreeData = NULL;
firstUsedData = NULL;
pool.resize(size);
resetPool();
}
//Resets the pool. Note that this isn't cheap because it must fix up the linked list
//that underlies the Pool structure
void clear()
{
totalActiveData = 0;
firstFreeData = NULL;
firstUsedData = NULL;
resetPool();
}
//Returns the first free data in the pool, or NULL if the pool is
//full.
PoolData<R>* getNewData()
{
if (firstFreeData != NULL) //Make sure the pool isn't full
{
PoolData<R>* freeData = firstFreeData;
firstFreeData = firstFreeData->nextFreeData;
//Link this data into the usedData linked list
if (firstUsedData != NULL) firstUsedData->nextUsedData = freeData;
freeData->nextUsedData = NULL;
freeData->prevUsedData = firstUsedData;
firstUsedData = freeData;
freeData->isActive = true;
totalActiveData++;
return freeData;
}
return NULL; //Pool is full
}
//Sets the data to inactive so that it can be used again.
void removeData(PoolData<R>* dataToRemove)
{
dataToRemove->nextFreeData = firstFreeData;
firstFreeData = dataToRemove;
//Unlinks this data from the usedData linked list
if (firstFreeData->prevUsedData)
firstFreeData->prevUsedData->nextUsedData = firstFreeData->nextUsedData;
totalActiveData--;
dataToRemove->isActive = false;
}
//Gets data at the requested index.
//Returns NULL if index isn't within range or data is not active
//Use getNextActiveData if you want to iterate through the pool
//(it uses nextUsedData to skip over inactive data)
PoolData<R>* getActiveDataAtIndex(unsigned int index)
{
//Index out of bounds
if (index > size) return NULL;
PoolData<R>* data = &pool[index];
if (data->isActive) return data;
else return NULL; //Data isn't in use
}
//Uses prevUsedData to skip over inactive data. This function will
//all fast iteration through active data in the pool. Break on NULL
PoolData<R>* getNextActiveData(PoolData<R>* currentData)
{
return currentData->prevUsedData;
}
//Returns the first active data (use in conjunction with getNextActiveData)
//to traverse the pool. Returns NULL if the pool is empty
PoolData<R>* getFirstActiveData()
{
return firstUsedData;
}
//Returns the total number of active data in the pool
unsigned int getTotalActiveData()
{
return totalActiveData;
}
};
#endif


+ 5
- 0
dataStructures/quadTree.cpp View File

@@ -0,0 +1,5 @@
#ifndef QUADTREE_CPP
#define QUADTREE_CPP
#include "quadTree.hpp"

#endif

+ 354
- 0
dataStructures/quadTree.hpp View File

@@ -0,0 +1,354 @@
#ifndef QUADTREE_HPP
#define QUADTREE_HPP
// For debug rendering
#include "../graphics/graphics.hpp"
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

#include <list>
#include <stdlib.h> /* system, NULL, EXIT_FAILURE */
#include "../collision/collision.hpp"
#include <iostream>

//TODO: Put into pool, remove std::vector data and replace with pool as well?

const unsigned int MAX_TREE_DEPTH = 8;
//If multiple QuadPoints are in the same place, tree will go to max depth,
//then capacity will become MAX_DEPTH_CAPACITY to handle the leftovers
const unsigned int MAX_DEPTH_CAPACITY = 100;
const float POINT_SEARCH_WIDTH = 1;
const float POINT_SEARCH_HEIGHT = 1;

//QuadPoints store the coordinate of the data along with the data itself
template<class R>
class QuadPoint
{
public:
float x;
float y;
R data;
};

/* --QuadTree--
* Template spacial quadtree
* I referred to http://en.wikipedia.org/wiki/Quadtree while coding this
* If >maxCapacity points are placed in the same position or cell, bad things
* will happen :(. Bad things won't make the structure not work, but it will
* make things less efficient. TODO: Fix this :(
* Make sure things are recursively subdivided and spread no matter what,
* unless n depth is reached (not so close points will still not be distributed?)
* */
template<class T>
class QuadTree
{
protected:
QuadTree* tL;
QuadTree* tR;
QuadTree* bL;
QuadTree* bR;
aabb bounds;

int maxCapacity;
std::list<QuadPoint<T> > data;
QuadTree(unsigned int newMaxCapacity, float newX, float newY, float newWidth, float newHeight, unsigned int newDepth)
{
depth = newDepth + 1;
maxCapacity = newMaxCapacity;
//Max depth reached; make sure this node holds a lot because
//it won't subdivide any more
if (depth >= MAX_TREE_DEPTH)
{
std::cout << "Max depth reached; setting capacity to MAX_DEPTH_CAPACITY\n";
maxCapacity = MAX_DEPTH_CAPACITY;
}
tL=NULL;
tR=NULL;
bL=NULL;
bR=NULL;
bounds.setPosition(newX, newY);
bounds.resize(newWidth, newHeight);
}
private:
void subdivide()
{
float halfWidth = bounds.w/2;
float halfHeight = bounds.h/2;
tL = new QuadTree<T>(maxCapacity, bounds.x, bounds.y, halfWidth, halfHeight, depth);
tR = new QuadTree<T>(maxCapacity, bounds.x + halfWidth, bounds.y, halfWidth, halfHeight, depth);
bL = new QuadTree<T>(maxCapacity, bounds.x, bounds.y + halfHeight, halfWidth, halfHeight, depth);
bR = new QuadTree<T>(maxCapacity, bounds.x + halfWidth, bounds.y + halfHeight, halfWidth, halfHeight, depth);

//Redistribute points into child nodes
while(!data.empty())
{
QuadPoint<T> newDataPoint = data.back();
T newData = newDataPoint.data;
float x = newDataPoint.x;
float y = newDataPoint.y;

if (tL->insert(newData, x, y))
{
data.pop_back();
continue;
}

if (tR->insert(newData, x, y))
{
data.pop_back();
continue;
}

if (bL->insert(newData, x, y))
{
data.pop_back();
continue;
}

if (bR->insert(newData, x, y))
{
data.pop_back();
continue;
}
//For some reason a point will not be accepted, so stop redistributing
break;
}
}
bool isPointInRange(float x, float y, aabb& range)
{
//See if point is within range
if (x <= range.x + range.w && x >= range.x && y <= range.y + range.h && y >= range.y)
{
return true;
}
return false;
}
public:
unsigned int depth;
QuadTree(unsigned int newMaxCapacity, float newX, float newY, float newWidth, float newHeight)
{
depth = 1;
maxCapacity = newMaxCapacity;
tL=NULL;
tR=NULL;
bL=NULL;
bR=NULL;
bounds.setPosition(newX, newY);
bounds.resize(newWidth, newHeight);
}
~QuadTree()
{
if (tL)
{
delete tR;
delete tL;
delete bR;
delete bL;
}
}
//Checks if node and its children are empty
bool isEmpty()
{
if (!data.empty()) return false;
if (!tL) return true;
if (tL->isEmpty() && tR->isEmpty() && bL->isEmpty() && bR->isEmpty())
{
return true;
}
return false;
}
bool insert(T newData, float x, float y)
{
//Make sure point is within the bounds of this node
if (!isPointInRange(x, y, bounds))
{
//Point is not within bounds
return false;
}
//Node isn't full yet, so add data to this node
if (!tL && data.size() < maxCapacity)
{
QuadPoint<T> newPoint;
newPoint.x = x;
newPoint.y = y;
newPoint.data = newData;
data.push_back(newPoint);
return true;
}

//Safety max depth
if (depth >= MAX_TREE_DEPTH)
{
std::cout << "\033[31mWARNING: Max tree depth (" << MAX_TREE_DEPTH << ") reached!\033[0m\n";
}
//Node is full; subdivide (if not already subdivided)
if (!tL)
{
subdivide();
}

//If already subdivided, try inserting into child nodes
if (tL->insert(newData, x, y)) return true;
if (tR->insert(newData, x, y)) return true;
if (bL->insert(newData, x, y)) return true;
if (bR->insert(newData, x, y)) return true;

// This shouldn't ever happen
return false;
}
//Returns false if the point could not be removed (it doesn't exist)
//data is used to make sure it is the point requested
//NOTE: X and Y are not used when comparing the point, just for walking the tree,
//so if you have two of the same data, it might not remove the one
//at the position specified (the system assumes you are using pointers)
bool remove(T searchData, float x, float y)
{
//Point will not be in this node's bounds
if(!isPointInRange(x, y, bounds)) return false;
//Search through points for the data
for (typename std::list<QuadPoint<T> >::iterator it = data.begin(); it!= data.end(); ++it)
{
//Found the data point; erase it (inefficient only in large vectors)
//TODO: Replace vector with list or something?
if ((*it).data==searchData)
{
data.erase(it);
return true;
}
}
//Search children (if any)
if (!tL) return false;
if (tL->remove(searchData, x, y) || tR->remove(searchData, x, y)
|| bL->remove(searchData, x, y) || bR->remove(searchData, x, y))
{
//All children are empty; delete them
if (isEmpty())
{
//TODO: Should this be a pool?
delete tL;
delete tR;
delete bL;
delete bR;
tL = NULL;
}
return true;
}

//Data point not in quadtree
return false;
}
//Fills the provided vector with resultant points (points
//contained in the specified range). Returns total results
unsigned int queryRange(aabb& range, std::vector<T>& results)
{
unsigned int totalResults = 0;
//Make sure range is touching this node
if (!isColliding(&range, &bounds))
{
return 0;
}
//Add points in this node to results if contained in range
for (typename std::list<QuadPoint<T> >::iterator it = data.begin(); it!=data.end(); ++it)
{
if (isPointInRange((*it).x, (*it).y, range))
{
results.push_back((*it).data);
totalResults++;
}
}

//Let all child nodes (if any) add points
if (!tL)
{
return totalResults;
}
totalResults += tL->queryRange(range, results);
totalResults += tR->queryRange(range, results);
totalResults += bL->queryRange(range, results);
totalResults += bR->queryRange(range, results);
return totalResults;
}
//Fills the provided array with resultant points (points
//contained in the specified range). Returns total results
//Pass in the maximum for the array as well as the index
//this function should start at (usually 0)
unsigned int queryRange(aabb& range, T* results, int& currentIndex, int maxPoints)
{
unsigned int totalResults = 0;
//Make sure the array isn't full
if (currentIndex >= maxPoints)
{
std::cout << "WARNING: queryPoints(): Results array full! (Max points = "<< maxPoints<< ")\n";
return totalResults;
}
//Make sure range is touching this node
if (!isColliding(&range, &bounds))
{
return 0;
}
//Add points in this node to results if contained in range
for (typename std::list<QuadPoint<T> >::iterator it = data.begin(); it!=data.end(); ++it)
{
if (isPointInRange((*it).x, (*it).y, range))
{
if (currentIndex < maxPoints)
{
results[currentIndex] = (*it).data;
totalResults++;
currentIndex++;
}
else
{
std::cout << "WARNING: queryPoints(): Results array full! (Max points = "<< maxPoints<< ")\n";
return totalResults;
}
}
}

//Let all child nodes (if any) add points
if (!tL)
{
return totalResults;
}
totalResults += tL->queryRange(range, results, currentIndex, maxPoints);
totalResults += tR->queryRange(range, results, currentIndex, maxPoints);
totalResults += bL->queryRange(range, results, currentIndex, maxPoints);
totalResults += bR->queryRange(range, results, currentIndex, maxPoints);
return totalResults;
}

void render(window* win, float viewX, float viewY)
{
sf::RenderWindow* sfWin = win->getBase();
sf::RectangleShape rectangle;
rectangle.setSize(sf::Vector2f(bounds.w, bounds.h));
rectangle.setFillColor(sf::Color::Transparent);
if (!data.empty())
{
rectangle.setOutlineColor(sf::Color::Blue);
}
else rectangle.setOutlineColor(sf::Color::Green);
if (depth >= MAX_TREE_DEPTH) rectangle.setOutlineColor(sf::Color::Red);
rectangle.setOutlineThickness(2);
rectangle.setPosition(viewX + bounds.x, viewY + bounds.y);
sfWin->draw(rectangle);

if (tL)
{
tL->render(win, viewX, viewY);
tR->render(win, viewX, viewY);
bL->render(win, viewX, viewY);
bR->render(win, viewX, viewY);
}
}
};
#endif

+ 97
- 0
graphics/imageManager.cpp View File

@@ -0,0 +1,97 @@
#ifndef IMAGEMANAGER_CPP
#define IMAGEMANAGER_CPP
#include <iostream>
#include "imageManager.hpp"

ImageManager::ImageManager()
{
}
ImageManager::~ImageManager()
{
}

bool ImageManager::load(eptFile* spec)
{
//Loop through all groups (representing images), loading images and subrects as we go
std::string imageHandle;
eptGroup* imageGroup = spec->getGroupFromIndex(0, imageHandle);
for (int i = 1; imageGroup != NULL; i++)
{
//Load the sprite
sprite* newSprite = new sprite();
if (!newSprite->load(imageGroup->getAttribute("_file").c_str())) return false;
sprites[imageHandle] = newSprite;
std::cout << "Loaded image " << imageGroup->getAttribute("_file") << " successfully\n";
//Load the subrects
std::string subRectHandle;
std::string subRectStr = imageGroup->getAttributeFromIndex(0, subRectHandle);
for (int n = 1; subRectStr != ""; n++)
{
//Attributes preceded by _ are not subRects (ignore them)
if (subRectHandle[0] != '_')
{
SubRect newSubRect;
//Get the subrect from the attr array ( {x, y, w, h} )
newSubRect.x = attrToArrayInt(subRectStr, 0);
newSubRect.y = attrToArrayInt(subRectStr, 1);
newSubRect.width = attrToArrayInt(subRectStr, 2);
newSubRect.height = attrToArrayInt(subRectStr, 3);
subRects[subRectHandle] = newSubRect;
}
//Get the next attribute
subRectStr = imageGroup->getAttributeFromIndex(n, subRectHandle);
}
//Get the next group
imageGroup = spec->getGroupFromIndex(i, imageHandle);
}
return true;
}
//Returns the sprite with the specified handle, or NULL if it doesn't exist
sprite* ImageManager::getSprite(const std::string& spriteName)
{
std::map<std::string, sprite*>::iterator findIt = sprites.find(spriteName);
if (findIt==sprites.end()) return NULL;
sprite* spr = findIt->second;
//Reset rotation
spr->setRotation(0);
//Reset subrect
spr->clearSubRect();
return spr;
}
//Returns the sprite with the desired subRect applied, or NULL if either
//do not exist
sprite* ImageManager::getSubRectSprite(const std::string& spriteName, const std::string& subRectName)
{
//Grab the sprite
sprite* spr = getSprite(spriteName);
if (!spr) return NULL;
//Grab the subrect
std::map<std::string, SubRect>::iterator findIt = subRects.find(subRectName);
if (findIt == subRects.end()) return NULL;
SubRect* rect = &findIt->second;
//Set the sprite subrect to the requested subRect
spr->setSubRect(rect->x, rect->y, rect->width, rect->height);
return spr;
}
//Returns the sprite with the desired subRect applied, or NULL if either
//do not exist
sprite* ImageManager::getSubRectSprite(const std::string& spriteName, const std::string& subRectName, SubRect& subRect)
{
//Grab the sprite
sprite* spr = getSprite(spriteName);
if (!spr) return NULL;
//Grab the subrect
std::map<std::string, SubRect>::iterator findIt = subRects.find(subRectName);
if (findIt == subRects.end()) return NULL;
SubRect* rect = &findIt->second;
//Set the sprite subrect to the requested subRect
spr->setSubRect(rect->x, rect->y, rect->width, rect->height);
//Pass the subRect pointer to the provided one (they want it)
subRect = *rect;
return spr;
}
#endif

+ 60
- 0
graphics/imageManager.hpp View File

@@ -0,0 +1,60 @@
#ifndef IMAGEMANAGER_HPP
#define IMAGEMANAGER_HPP
#include <map>
#include "graphics.hpp"
#include "../ept/eptParser.hpp"

struct SubRect
{
int x;
int y;
int width;
int height;
};
/**--ImageManager--
* ImageManager holds all sprites and subRects. It loads the images automatically
* and provides a convenient interface for requesting them. The integration
* of subRects encourages use of spritesheets.
* */
class ImageManager
{
private:
std::map<std::string, SubRect> subRects;
std::map<std::string, sprite*> sprites;
public:
ImageManager();
~ImageManager();

//Load all images in the spec
bool load(eptFile* spec);
//Returns the sprite with the specified handle, or NULL if it doesn't exist
//Note that this function also resets the subrect and rotation of the sprite
sprite* getSprite(const std::string& spriteName);
//Returns the sprite with the desired subRect applied, or NULL if it
//doesn't exist
sprite* getSubRectSprite(const std::string& spriteName, const std::string& subRectName);
//Returns the sprite with the desired subRect applied, or NULL if it
//doesn't exist. Also returns a reference to the subRect used on the image
sprite* getSubRectSprite(const std::string& spriteName, const std::string& subRectName, SubRect& subRect);
};
/* EPT specification
* <imageManager.1>
*
* //image handle
* hud:
* //Filename, preceded by _
* _file=data/images/hud.png
* //All other attributes not preceded by '_' are treated as subrects
* healthBackground={0, 0, 400, 100};
* healthForeground={100, 100, 400, 100};
* //(in the format {x, y, width, height}; )
* //In the future, animations will be defined via #, e.g.
* #anim1={0, 0, 32, 32, 8, 24};
* //defined like so: {x, y, singleFrameW, h, totalFrames, FPS}
*
* You can then get the set up sprite by calling this (e.g.):
* sprite* hudBackground = imageManager.getSubRectSprite("hud", "healthBackground");
* and it's ready to render!
* */
#endif

+ 66
- 0
input/inputState.cpp View File

@@ -0,0 +1,66 @@
#ifndef INPUTSTATE_CPP
#define INPUTSTATE_CPP
#include "inputState.hpp"
#include <iostream>
InputState::InputState()
{
inputMan = NULL;
inputSource = Source::INPUT_MANAGER; //By default
}
//Populates inputs map with the inputs specified in the spec;
//sets Source depending on the second parameter
void InputState::setup(eptGroup* spec, inputManager* newInputManager)
{
//Prepare source
inputMan = newInputManager;
inputSource = Source::INPUT_MANAGER;

//Prepare inputs map
std::string attrName;
std::string codeStr = spec->getAttributeFromIndex(0, attrName);
for (int i = 1; codeStr != ""; i++)
{
Input newInput;
newInput.name = attrName;
newInput.code = attrToInt(codeStr);
newInput.state = 0;
inputs[attrName] = newInput;
//Get next attribute
codeStr = spec->getAttributeFromIndex(i, attrName);
}
}

//Updates the states of all inputs in the inputs map
//Will eventually be able to read these from a file or network
void InputState::update()
{
for (std::map<std::string, Input>::iterator it = inputs.begin();
it != inputs.end(); ++it)
{
Input* currentInput = &it->second;
//Update the state of the current input (depending on source)
switch (inputSource)
{
case Source::INPUT_MANAGER:
currentInput->state = inputMan->getState(currentInput->code);
break;
default:
break;
}
}
}

//Returns the current state of the input (since last update()) or
//0 if the input does not exist (which also causes an error to be printed)
int InputState::getInputState(const std::string& inputName)
{
std::map<std::string, Input>::iterator findIt = inputs.find(inputName);
if (findIt == inputs.end())
{
std::cout << "ERROR: InputState.getInputState(): Entry for input " << inputName << " doesn't exist!\n";
return 0;
}
return findIt->second.state;
}
#endif


+ 85
- 0
input/inputState.hpp View File

@@ -0,0 +1,85 @@
#ifndef INPUTSTATE_HPP
#define INPUTSTATE_HPP

#include <map>

#include "input.hpp"
#include "../ept/eptParser.hpp"

//Input holds a named input with universal code and state variables
struct Input
{
int code; //Universal key and mouse code
std::string name; //Name of this specific input (e.g. 'pause')
int state; //Universal key state (0 or 1 for binary inputs
//(e.g. space); -x to +x for variable inputs (e.g.
//mouse))
};
/* --InputState--
* InputState stores the state of all inputs of interest (as defined by
* an EPT spec) as abstract handles. This allows defining of inputs by
* function rather than by input.
*
* For example, instead of querying a mouse button, you would query "attack",
* which was defined in a EPT spec as SPACE. This makes very simple configurable
* input!
*
* Additionally, InputStates can be stored for input recording, which allows
* replays and makes testing easier. (TODO)
* */
class InputState
{
//Where the inputs will be collected from
enum Source
{
INPUT_MANAGER, //Get the input from a standard inputManager
FILE, //Get the input from a file (TODO)
NETWORK //Get the input from the network (TODO)
};
private:
std::map<std::string, Input> inputs;
Source inputSource;
inputManager* inputMan;
public:
InputState();
//Populates inputs map with the inputs specified in the spec;
//sets Source depending on the second parameter
void setup(eptGroup* spec, inputManager* newInputManager);
//TODO (possibly)
//void setup(eptFile* spec, InputRecording* recording);
//void setup(eptFile* spec, InputNetworked* networkInput);

//Updates the states of all inputs in the inputs map
//Will eventually be able to read these from a file or network
void update();

//Returns the current state of the input (since last update()) or
//0 if the input does not exist (which also causes an error to be printed)
int getInputState(const std::string& inputName);
};
/* --EPT Specification--
* The EPT spec should be defined as follows:
* <myInput.1>
* //Group names do not matter as you will be passing in a single
* //group (use them to pick the right input mode); this functions
* // as a useful mechanism for having different input modes and
* //configurations in the same .ept file
* menuControls:
* //Provide the name of the input as well as the universal code of
* //the input; check base2.0/input/input.hpp for input codes
* back=43;
* accept=63;
* gameplayControls:
* forward=55;
* backward=54;
* pause=100;
* //etc.
*
* You would then create an InputState like so:
* InputState menuControlInputs;
* menuControlInputs.setup(parser.getGroup("myInput.menuControls"), inputMan);
* //And
* InputState gameplayControlInputs;
* gameplayControlInputs.setup(parser.getGroup("myInput.gameplayControls"), inputMan);
* */
#endif

+ 25
- 2
makefile View File

@@ -2,10 +2,17 @@ FLAGS=g++ -std=c++11 -c -Os -Wall
ARCHIVE_NAME=lib/base.a
OBJ_DIR=LOCAL_obj

all: noise.o eptParser.o math.o collision.o timer.o profiler.o graphics.o input.o tileMap.o multilayerMap.o tileCamera.o animation.o sound.o
all: pool.o quadTree.o noise.o eptParser.o math.o collision.o timer.o profiler.o graphics.o imageManager.o input.o inputState.o tileMap.o multilayerMap.o tileCamera.o animation.o sound.o
@echo -------------------Building archive...
ar rvs $(ARCHIVE_NAME) noise.o eptParser.o math.o collision.o graphics.o input.o tileMap.o multilayerMap.o tileCamera.o animation.o timer.o profiler.o sound.o
ar rvs $(ARCHIVE_NAME) pool.o quadTree.o noise.o eptParser.o math.o collision.o graphics.o imageManager.o input.o inputState.o tileMap.o multilayerMap.o tileCamera.o animation.o timer.o profiler.o sound.o
#mv *.o $(OBJ_DIR)

pool.o: dataStructures/pool.hpp dataStructures/pool.cpp
$(FLAGS) "dataStructures/pool.hpp"
$(FLAGS) "dataStructures/pool.cpp"
quadTree.o: dataStructures/quadTree.hpp dataStructures/quadTree.cpp
$(FLAGS) "dataStructures/quadTree.hpp"
$(FLAGS) "dataStructures/quadTree.cpp"
noise.o: noise/noise.hpp noise/noise.cpp
$(FLAGS) "noise/noise.hpp"
$(FLAGS) "noise/noise.cpp"
@@ -27,9 +34,15 @@ profiler.o: profiler/profiler.hpp profiler/profiler.cpp
graphics.o: graphics/graphics.hpp graphics/graphics.cpp
$(FLAGS) "graphics/graphics.hpp"
$(FLAGS) "graphics/graphics.cpp"
imageManager.o: graphics/imageManager.hpp graphics/imageManager.cpp
$(FLAGS) "graphics/imageManager.hpp"
$(FLAGS) "graphics/imageManager.cpp"
input.o: input/input.hpp input/input.cpp
$(FLAGS) "input/input.hpp"
$(FLAGS) "input/input.cpp"
inputState.o: input/inputState.hpp input/inputState.cpp
$(FLAGS) "input/inputState.hpp"
$(FLAGS) "input/inputState.cpp"
tileMap.o: tileMap/tileMap.hpp tileMap/tileMap.cpp
$(FLAGS) "tileMap/tileMap.hpp"
$(FLAGS) "tileMap/tileMap.cpp"
@@ -76,6 +89,7 @@ clean:
rm ept/*.gch
rm animation/*.gch
rm noise/*.gch
rm dataStructures/*.gch
#rm 3rdParty/*.gch
@echo -------------------If base is installed, removing it... [root priveleges]
rm /usr/lib/libbase2.0.a
@@ -97,6 +111,7 @@ install:
mkdir /usr/include/base2.0
mkdir /usr/include/base2.0/3rdParty
mkdir /usr/include/base2.0/noise
mkdir /usr/include/base2.0/dataStructures
mkdir /usr/include/base2.0/ept
mkdir /usr/include/base2.0/math
mkdir /usr/include/base2.0/collision
@@ -109,6 +124,8 @@ install:
mkdir /usr/include/base2.0/animation
@echo -------------------Installing header files to /usr/include/base2.0...
cp 3rdParty/OpenSimplexNoise.hh /usr/include/base2.0/3rdParty/OpenSimplexNoise.hh
cp dataStructures/pool.hpp /usr/include/base2.0/dataStructures/pool.hpp
cp dataStructures/quadTree.hpp /usr/include/base2.0/dataStructures/quadTree.hpp
cp noise/noise.hpp /usr/include/base2.0/noise/noise.hpp
cp math/math.hpp /usr/include/base2.0/math/math.hpp
cp ept/eptParser.hpp /usr/include/base2.0/ept/eptParser.hpp
@@ -116,7 +133,9 @@ install:
cp timer/timer.hpp /usr/include/base2.0/timer/timer.hpp
cp profiler/profiler.hpp /usr/include/base2.0/profiler/profiler.hpp
cp graphics/graphics.hpp /usr/include/base2.0/graphics/graphics.hpp
cp graphics/imageManager.hpp /usr/include/base2.0/graphics/imageManager.hpp
cp input/input.hpp /usr/include/base2.0/input/input.hpp
cp input/inputState.hpp /usr/include/base2.0/input/inputState.hpp
cp tileMap/tileMap.hpp /usr/include/base2.0/tileMap/tileMap.hpp
cp tileMap/multilayerMap.hpp /usr/include/base2.0/tileMap/multilayerMap.hpp
cp tileMap/tileCamera.hpp /usr/include/base2.0/tileMap/tileCamera.hpp
@@ -127,6 +146,8 @@ update:
cp lib/base.a /usr/lib/libbase2.0.a
@echo -------------------Installing header files to /usr/include/base2.0...
cp 3rdParty/OpenSimplexNoise.hh /usr/include/base2.0/3rdParty/OpenSimplexNoise.hh
cp dataStructures/pool.hpp /usr/include/base2.0/dataStructures/pool.hpp
cp dataStructures/quadTree.hpp /usr/include/base2.0/dataStructures/quadTree.hpp
cp noise/noise.hpp /usr/include/base2.0/noise/noise.hpp
cp math/math.hpp /usr/include/base2.0/math/math.hpp
cp ept/eptParser.hpp /usr/include/base2.0/ept/eptParser.hpp
@@ -134,7 +155,9 @@ update:
cp timer/timer.hpp /usr/include/base2.0/timer/timer.hpp
cp profiler/profiler.hpp /usr/include/base2.0/profiler/profiler.hpp
cp graphics/graphics.hpp /usr/include/base2.0/graphics/graphics.hpp
cp graphics/imageManager.hpp /usr/include/base2.0/graphics/imageManager.hpp
cp input/input.hpp /usr/include/base2.0/input/input.hpp
cp input/inputState.hpp /usr/include/base2.0/input/inputState.hpp
cp tileMap/tileMap.hpp /usr/include/base2.0/tileMap/tileMap.hpp
cp tileMap/multilayerMap.hpp /usr/include/base2.0/tileMap/multilayerMap.hpp
cp tileMap/tileCamera.hpp /usr/include/base2.0/tileMap/tileCamera.hpp


Loading…
Cancel
Save