domingo, 31 de marzo de 2013

PakEngine. Capitulo 18. Interficie C++. Clase Sprite.

Artículo perteneciente a la sección del PakEngine

Hola a todos,

No hace mucho que escribí un articulo que trataba sobre la pereza de reescribir código y sus efectos malignos en el código. Y como no podía ser de otra manera debo aplicar lo que digo.

El caso es que hice un error de diseño bastante grande presuponiendo que la interficie de C y C++ podrían ser idénticas cambiando solamente la nomenclatura, pero esto , obviamente, no es posible. Si lo hiciera, la complejidad ciclomática se me dispararía y acabaría por abandonar el proyecto, así que las cosas quedan de la siguiente manera:
Interficie C: Se podrán realizar pintados normales y con rotación. No se podrá hacer más por que sino la complejidad aumentaría de forma exponencial.
Interficie C++: Se trabajará directamente sobre objetos de tipo sprite que permitirán multitud de modificaciones sobre el pintado. Esto es así por que la estructura usada en C++ permite crecer el número de funcionalidades sin aumentar prácticamente la complejidad.

El código del drawobject (el objeto que se encarga de realizar el pintado final ) queda tal que así:

DrawObject::DrawObject(int tx, int ty, int tz, int tid, float tangle,float tescale, bool tflipx, bool tflipy)
{
x = tx;
y = ty;
z = tz;
id = tid;
angle = tangle;
escale = tescale;
flipx = tflipx;
flipy = tflipy;
}

void DrawObject::Draw(void)
{
int tex,w,h;
int center_x,center_y;
float xini,yini,xend,yend;

tex = SPRITELIST_GetTexture(id);
w = SPRITELIST_GetWidth(id);
h = SPRITELIST_GetHeight(id);

w *= escale;
h *= escale;

w/= 100.0;
h/= 100.0;

glAlphaFunc(GL_GREATER,0.1f);
glEnable(GL_ALPHA_TEST);

glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

center_x = x + w/2 ;
center_y = y + h/2 ;

if(flipx)
{
xini = 1.0f;
xend = 0.0f;
}
else
{
xini = 0.0f;
xend = 1.0f;
}

if(flipy)
{
yini = 1.0f;
yend = 0.0f;
}
else
{
yini = 0.0f;
yend = 1.0f;
}

glPushMatrix();

glTranslatef( (GLfloat) center_x, (GLfloat) center_y, 0 );
glRotatef( angle , 0, 0, 1 );
glTranslatef( - (GLfloat) center_x, - (GLfloat) center_y, 0 );

glBegin(GL_QUADS);
glTexCoord2f( xend, yend); glVertex2i( x + w , y + h );
glTexCoord2f( xini, yend); glVertex2i( x     , y + h );
glTexCoord2f( xini, yini); glVertex2i( x     , y  );
glTexCoord2f( xend, yini); glVertex2i( x + w    , y );
glEnd();

glPopMatrix();

};


Y la interficie de la clase sprite la podéis encontrar en el svn dentro del pakengine.h (para que sea accesible desde el juego). No está acabada pero si que tiene lo más importante.

class DLLEXPORT Sprite
{
private:
int graf;
int x,y,z;
float angle;
float escale;
bool flipx,flipy;
bool visible;

public:
Sprite(void);
~Sprite(void);

//Seters
void SetGraf(int id);
void SetGraf(char *cad);

void Move(int incx, int incy);
void Move(int incx, int incy, int incz);

void MoveTo(int x, int y);
void MoveTo(int x, int y, int z);

void Rotate(float inc_angle);
void RotateTo(float angle);

void Escale(float inc_escale);
void EscaleTo(float escale);

void FlipX(void);
void FlipY(void);
void FlipXY(void);

void RestoreToDefaults(void);

void Push(void);
void Pop(void);

void SetVisible(bool visible);

//Geters
int GetX(void);
int GetY(void);
int GetZ(void);

float GetAngle(void);
float GetEscale(void);

bool IsFlippedinX(void);
bool IsFlippedinY(void);

bool IsVisible(void);

//Others
void Draw(void);
};




Aquí teneís un ejemplo de código de como usar la nueva clase de pintado:

int main(void)
{
Sprite *fondo;
Sprite *nave[10] = {0};
int i;

PakEngine p("Pakteroids",1024,750);

fondo = new Sprite();
fondo->SetGraf("Resources\\estrellas.jpg");
fondo->MoveTo(0,0,100);
fondo->SetVisible(true);

for( i = 0 ; i < 10 ; ++i)
{
nave[i] = new Sprite();
nave[i]->SetGraf("Resources\\nave.png");
nave[i]->SetVisible(true);
}

nave[0]->MoveTo(100,100,20);

nave[1]->MoveTo(200,200,30);
nave[1]->EscaleTo(0.0);

nave[2]->MoveTo(300,500,40);
nave[2]->EscaleTo(0.0);

nave[3]->MoveTo(100,200,25);
nave[3]->EscaleTo(45.0f);

nave[4]->MoveTo(200,550,25);
nave[4]->EscaleTo(-45.0f);

nave[5]->MoveTo(400,100,50);
nave[5]->FlipX();

nave[6]->MoveTo(500,650,50);
nave[6]->FlipY();

nave[7]->MoveTo(600,100,50);
nave[7]->FlipXY();

nave[8]->MoveTo(700,500,60);
nave[8]->FlipY();

nave[9]->MoveTo(800,600,70);
nave[9]->FlipXY();
nave[9]->EscaleTo(300.0f);

while(p.Render())
{
fondo->Draw();

for( i = 0 ; i < 10 ; ++i)
{
if(nave[i])
nave[i]->Draw();
}

nave[0]->Rotate(0.1f);

nave[1]->Escale(1.0f);

nave[2]->Escale(0.5f);
nave[2]->Rotate(-0.5f);

nave[8]->Rotate(2.0f);

nave[9]->Escale(-1.0f);
}
}



Y aquí os dejo el video de muestra de como funciona la clase Sprite


Espero que os haya gustado y os animéis a hacer vuestras primeras pruebas.

Nos vemos.

LordPakusBlog

0 comentarios :

Publicar un comentario

Entradas populares