#ifndef CLL__H
#define CLL__H
template <class T>
class cllNode
{
public:
cllNode<T>* pNext;
cllNode<T>* pPrev;
T value;
};
template <class T>
class CircularLinkedList
{
public:
CircularLinkedList()
{
pStart = 0;
pEnd = 0;
pSeek = 0;
}
~CircularLinkedList();
cllNode<T>* pStart;
cllNode<T>* pEnd;
cllNode<T>* pSeek;
void Add(T);
T Get();
void SeekForward();
void SeekBack();
};
template <class T>
CircularLinkedList<T>::~CircularLinkedList()
{
cllNode<T>* pNode; // This node steps through the array
cllNode<T>* pNxt; // Used to store the next node up for deletion
pNode = pStart; // We start from the beginning
while (pNode) // We delete everything in this loop
{
pNxt = pNode->pNext; // Store the next address
delete pNode; // Delete current node
pNode = pNxt; // Move up
}
}
template <class T>
void CircularLinkedList<T>::Add(T new_value)
{
cllNode<T>* pNew; // This is our new node
pNew = new cllNode<T>; // Allocate memory for it
pNew->value = new_value; // Store the value
if (!pStart) // If there's no nodes...
{
pNew->pPrev = pNew; // The new node is the only node,
pNew->pNext = pNew; // so the first, last, next, and
pStart = pNew; // previous are all this node.
pEnd = pNew;
pSeek = pNew;
}
else // If there are nodes...
{
pNew->pPrev = pEnd; // The last node is this node's previous
pNew->pNext = pStart; // The first node is this node's next
pEnd = pNew; // The last node is now this node
}
}
template <class T>
T CircularLinkedList<T>::Get()
{
return pSeek->value; // Return the value at the seek pointer
}
template <class T>
void CircularLinkedList<T>::SeekForward()
{
pSeek = pSeek->pNext; // Move the seek pointer forward
}
template <class T>
void CircularLinkedList<T>::SeekBack()
{
pSeek = pSeek->pPrev; // Move the seek pointer backward
}
#endif
#ifndef CHARSELCIRCLE__H
#define CHARSELCIRCLE__H
#include <allegro.h>
#include <alleggl.h>
#include "cll.h"
#include "texture.h"
#define SEL_CIRC_FILE "charselcircle.tga"
#define FEMALE_MAGUS_FILE "f_magus_c.tga"
#define FEMALE_SOLDIER_FILE "f_soldier_c.tga"
#define NUMBER_OF_TYPES 4.0f
#define NUMBER_OF_TYPES_i 4
#define SMALL_CIRC_DEGS 39.0f
#define SPIN_SPEED 1.0f
#define F_MAGUS_S_FILE "f_magus_s.tga"
#define F_SOLDIER_S_FILE "f_soldier_s.tga"
#define PI 3.1415f
#define SMALL_FACE_SIZE 75
#define CIRCLE_SIZE 200.0f
#define CIRCLE_X 170.0f
#define CIRCLE_Y 166.0f
class CharSelCircle
{
private:
Texture Textures;
Texture SmallFaces;
Texture Characters;
bool spinning_cw;
bool spinning_ccw;
int selected;
float circ_x;
float circ_y;
float starting_degrees;
CircularLinkedList<GLuint> small_face_textures;
public:
CharSelCircle();
~CharSelCircle();
void Update();
void Draw();
};
#endif
#include <allegro.h>
#include <alleggl.h>
#include <cmath>
#include "charselcircle.h"
#include "cll.h"
#include "texture.h"
CharSelCircle::CharSelCircle()
{
spinning_cw = false;
spinning_ccw = false;
face_order_needs_update = true;
selected = 0;
starting_degrees = SMALL_CIRC_DEGS;
Textures.Load("select_circle", SEL_CIRC_FILE);
Characters.Load("female_magus", FEMALE_MAGUS_FILE);
Characters.Load("female_soldier", FEMALE_SOLDIER_FILE);
SmallFaces.Load("f_magus_s", F_MAGUS_S_FILE);
SmallFaces.Load("f_soldier_s", F_SOLDIER_S_FILE);
SmallFaces.Load("f_soldier_s", F_MAGUS_S_FILE);
SmallFaces.Load("f_soldier_s", F_SOLDIER_S_FILE);
small_face_textures.Add(SmallFaces.At(0));
small_face_textures.Add(SmallFaces.At(1));
small_face_textures.Add(SmallFaces.At(2));
small_face_textures.Add(SmallFaces.At(3));
}
CharSelCircle::~CharSelCircle()
{
/* Destructor */
}
void CharSelCircle::Update()
{
//TEST CONTROLS
if ((!spinning_cw) && (!spinning_ccw))
{
if (key[KEY_LEFT])
{
spinning_cw = true;
}
if (key[KEY_RIGHT])
{
spinning_ccw = true;
}
}
// What to do if we're spinning clockwise
if (spinning_cw)
{
// Do the actual spin
starting_degrees += SPIN_SPEED;
// If the spin is complete, reset everything and change the selection
if (starting_degrees >= SMALL_CIRC_DEGS + (360.0f / NUMBER_OF_TYPES))
{
starting_degrees = SMALL_CIRC_DEGS;
spinning_cw = false;
selected += 1;
small_face_textures.SeekForward();
// Keep the selection value in bounds
if (selected >= (int)NUMBER_OF_TYPES)
{
selected = 0;
}
}
}
// What to do if we're spinning counter-clockwise
if (spinning_ccw)
{
// Do the actual spin
starting_degrees -= SPIN_SPEED;
// If the spin is complete, reset everything and change the selection
if (starting_degrees <= SMALL_CIRC_DEGS - (360.0f / NUMBER_OF_TYPES))
{
starting_degrees = SMALL_CIRC_DEGS;
spinning_ccw = false;
selected -= 1;
small_face_textures.SeekBack();
// Keep the selection value in bounds
if (selected < 0)
{
selected = (int)NUMBER_OF_TYPES - 1;
}
}
}
}
void CharSelCircle::Draw()
{
// Get a clean slate of attributes
glPushAttrib(GL_ENABLE_BIT);
for (float circ_angle = starting_degrees; circ_angle <= 360.0f + starting_degrees; circ_angle += (360.0f / NUMBER_OF_TYPES))
{
circ_x = CIRCLE_SIZE * cos(circ_angle * (PI / 180.0f));
circ_y = CIRCLE_SIZE * sin(circ_angle * (PI / 180.0f));
// Set up to draw
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST); // Needed for transparency
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, small_face_textures.Get());
small_face_textures.SeekForward();
// White polygon
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
// Draw it
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex2f((circ_x - (SMALL_FACE_SIZE / 2.0f)) + CIRCLE_X, (circ_y + (SMALL_FACE_SIZE / 2.0f)) + CIRCLE_Y);
glTexCoord2f(1.0f, 0.0f); glVertex2f((circ_x + (SMALL_FACE_SIZE / 2.0f)) + CIRCLE_X, (circ_y + (SMALL_FACE_SIZE / 2.0f)) + CIRCLE_Y);
glTexCoord2f(1.0f, 1.0f); glVertex2f((circ_x + (SMALL_FACE_SIZE / 2.0f)) + CIRCLE_X, (circ_y - (SMALL_FACE_SIZE / 2.0f)) + CIRCLE_Y);
glTexCoord2f(0.0f, 1.0f); glVertex2f((circ_x - (SMALL_FACE_SIZE / 2.0f)) + CIRCLE_X, (circ_y - (SMALL_FACE_SIZE / 2.0f)) + CIRCLE_Y);
glEnd();
}
glPopAttrib();
}