PDA

View Full Version : OpenGL, DevIL, C++, How to animate tilesheet?



PocketTNT
05-22-2016, 02:22 PM
I've made my gif into a tilesheet and can render it just fine. Now I need to know how to make it change the Y coordinate while the program is running to animate it without crashing.



#include "LUtil.h"
#include <IL/il.h>
#include <IL/ilu.h>
#include "LSpriteSheet.h"

int add = 0;
int zoom = 0;
int factor = 0;
int factor2 = 0;
float y = 0.f;
int scroll = 0;
GLfloat gCameraX = 0.f, gCameraY = 0.f, gCameraZ = 0.f;

//Sprite texture

LSpriteSheet gArrowSprites;
LSpriteSheet gGIFSprites;

bool initGL()
{
//Initialize GLEW
GLenum glewError = glewInit();
if( glewError != GLEW_OK )
{
printf( "Error initializing GLEW! %s\n", glewGetErrorString( glewError ) );
return false;
}

//Make sure OpenGL 2.1 is supported
if( !GLEW_VERSION_2_1 )
{
printf( "OpenGL 2.1 not supported!\n" );
return false;
}

//Set the viewport
glViewport( 0.f, 0.f, SCREEN_WIDTH, SCREEN_HEIGHT );

//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, 5.0, -5.0 );

//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

glPushMatrix();

//Initialize clear color
glClearColor( 0.f, 0.f, 0.f, 1.f );

//Enable texturing
glEnable( GL_TEXTURE_2D );

glEnable( GL_BLEND );
glDisable( GL_DEPTH_TEST );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

//Check for error
GLenum error = glGetError();
if( error != GL_NO_ERROR )
{
printf( "Error initializing OpenGL! %s\n", gluErrorString(error));
return false;
}

//Initialize DevIL
ilInit();
ilClearColour( 255, 255, 255, 000 );

//Check for error
ILenum ilError = ilGetError();
if( ilError != IL_NO_ERROR )
{
printf( "Error initializing DevIL! %s\n", iluErrorString(ilError) );
return false;
}

return true;
}


bool loadMedia()
{

//Load texture
if( !gArrowSprites.loadTextureFromFile( "StillSpriteSheet.png" ) )
{
printf( "Unable to load texture!\n" );
return false;
}
LFRect clip = { 0.f, 0.f, 330.f, 355.f };

//Top left
clip.x = 0.f;
clip.y = 0.f;
gArrowSprites.addClipSprite( clip );

//Top right
clip = {0.f, 0.f, 310.f, 480.f};

clip.x = 331.f;
clip.y = 0.f;
gArrowSprites.addClipSprite( clip );

clip = {0.f, 0.f, 330.f, 125.f};
//Bottom left
clip.x = 0.f;
clip.y = 355.f;

gArrowSprites.addClipSprite( clip );

clip = { 0.f, 0.f, 330.f, 355.f };

//Top left
clip.x = 0.f;
clip.y = 480.f;
gArrowSprites.addClipSprite( clip );

//Top right
clip = {0.f, 0.f, 310.f, 480.f};

clip.x = 331.f;
clip.y = 480.f;
gArrowSprites.addClipSprite( clip );

clip = {0.f, 0.f, 330.f, 125.f};
//Bottom left
clip.x = 0.f;
clip.y = 835.f;

gArrowSprites.addClipSprite( clip );
//Generate VBO
if( !gArrowSprites.generateDataBuffer() )
{
printf( "Unable to clip sprite sheet!\n" );
return false;
}
if( !gGIFSprites.loadTextureFromFile( "TileSheet.png" ) )
{
printf( "Unable to load texture!\n" );
return false;
}

clip = {0.f, 0.f, 213.f, 214.f};

clip.x = 0.f;
clip.y = y;

for (scroll = 0; scroll < 40; ++scroll, clip.y += 214.f, SCREEN_FPS % 10 ){
glutSwapBuffers();
if(scroll == 39){
scroll = 0;
}
}

gGIFSprites.addClipSprite( clip );

if( !gGIFSprites.generateDataBuffer() )
{
printf( "Unable to clip sprite sheet!\n" );
return false;
}
return true;
}

void update()
{

}

void render()
{
//Clear color buffer

glClear( GL_COLOR_BUFFER_BIT );

glMatrixMode(GL_MODELVIEW);
glPopMatrix();

glPushMatrix();

if(add == 0){
if(zoom < 101){
double const f_zoom = 1.0 + 0.1 * zoom;
glScaled(f_zoom, f_zoom, f_zoom);
}
if(zoom < -10){
double const f_zoom = 1.0 - 0.1 * zoom;
glScaled(f_zoom, f_zoom, f_zoom);
}

glTranslatef( -100.f, 178.f, 0.f );
gArrowSprites.renderSprite( 0 );

//Render top right arrow
glTranslatef( +100.f, -178.f, 0.f );
glTranslatef( 1240.f, 240.f, 0.f );
gArrowSprites.renderSprite( 1 );

//Render bottom left arrow
glTranslatef( -1240.f, +240.f, 0.f );
glTranslatef( 620.f, 500.f ,0.f );
gArrowSprites.renderSprite( 2 );

glTranslatef( -620.f, -500.f, 0.f );
glTranslatef( 620.f, 0.f , 0.f );
gGIFSprites.renderSprite( 0 );

}
if(add == 1){
if(zoom < 101){
double const f_zoom = 1.0 + 0.1 * zoom;
glScaled(f_zoom, f_zoom, f_zoom);
}
if(zoom < -10){
double const f_zoom = 1.0 - 0.1 * zoom;
glScaled(f_zoom, f_zoom, f_zoom);
}

glTranslatef( -100.f, 178.f, 0.f );
gArrowSprites.renderSprite( 3 );

glTranslatef( +100.f, -178.f, 0.f );
glTranslatef( 1240.f, 240.f, 0.f );
gArrowSprites.renderSprite( 4 );

glTranslatef( -1240.f, +240.f, 0.f );
glTranslatef( 620.f, 500.f ,0.f );
gArrowSprites.renderSprite( 5 );
}

glLoadIdentity();


glutSwapBuffers();

}
void handleKeys( unsigned char key, int x, int y )
{
//If the user presses q
if( key == 'q' && add == 0)
{
add++;
}
else if( key == 'q' && add == 1)
{
add--;
}
//Update the sprite rectangles so the texture change takes effect
if( key == 27 ) {
exit(0);
}
if(key == 'a') {
gCameraX += 8.f;
factor--;
factor2++;
}
else if (key == 'd') {
gCameraX -= 8.f;
factor++;
factor2--;
}
else if (key == 'w') {
gCameraY += 8.f;
}
else if (key == 's') {
gCameraY -= 8.f;
}
else if (key == '+' && zoom != 100) {
zoom += 1;
if(factor >= 19) {
gCameraX -= 64.f;
}
if(factor2 >= 33){
gCameraX += 16.f;
}
else{
gCameraX -= 64.f;
gCameraY -= 50.f;
}
}
else if (key == '-' && zoom != -9) {
zoom -= 1;
if(factor >= 19){
gCameraX += 64.f;
}
if(factor2 >= 33){
gCameraX -= 32.f;
}
else{
gCameraX += 64.f;
gCameraY += 50.f;
}
}
//Take saved matrix off the stack and reset it
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
glLoadIdentity();

//Move camera to position
glTranslatef( gCameraX, gCameraY, gCameraZ );

//Save default matrix again with camera translation
glPushMatrix();
}


Right now the while loop causes a crash and I assume that it's because I don't have an FPS limit on it, but I don't know how to implement that.
Also I know the loop can run because when I remove the if statement that resets the loop it doesn't crash but it stops on the last frame.
Any help?

EDIT: Updated the loop.

Update on issue: In the new loop, if 39 is changed to 40 it stops on the last frame. If 39 is kept as it is it will crash while on a black screen.

Carmine
05-22-2016, 06:23 PM
Sounds like a memory leak.

PocketTNT
05-22-2016, 07:19 PM
Sounds like a memory leak.

How can I fix it though?

john_connor
05-22-2016, 07:27 PM
Right now the while loop causes a crash and I assume that it's because I don't have an FPS limit on it, but I don't know how to implement that.

you just need a clock
then in your main loop, you only call update() and render IF enough time is passed since the last frame
BUT: by default, vsync is on, which means your fps cant get over 60 (frequency of the monitor)
only if you disable vsync, fps can go up to about 3000 or so ...




#define FPS_GOAL 60

...
static double tnow(0), tlast(0), tframe(0);
tnow = m_time.GetTime(); // http://www.cplusplus.com/reference/chrono/high_resolution_clock/now/
tframe = tnow - tlast;
if (tframe < 1.0 / FPS_GOAL)
continue;
tlast = tnow;

// update(tframe);
// render();

Carmine
05-22-2016, 11:24 PM
How can I fix it though?First, confirm it by monitoring how much RAM your application uses while it is running. If you have a leak, it will show up clearly. RAM usage will go up until the app. crashes.

PocketTNT
05-23-2016, 07:09 AM
you just need a clock
then in your main loop, you only call update() and render IF enough time is passed since the last frame
BUT: by default, vsync is on, which means your fps cant get over 60 (frequency of the monitor)
only if you disable vsync, fps can go up to about 3000 or so ...




#define FPS_GOAL 60

...
static double tnow(0), tlast(0), tframe(0);
tnow = m_time.GetTime(); // http://www.cplusplus.com/reference/chrono/high_resolution_clock/now/
tframe = tnow - tlast;
if (tframe < 1.0 / FPS_GOAL)
continue;
tlast = tnow;

// update(tframe);
// render();


Yeah, that's what I thought. But where am I supposed to put it? I've never made my own clock so I have no idea what to do with it.
Edit: I modified my loop a bit