如何为我的 GIF tilesheet 制作动画(OpenGL、DevIL、C++)

Posted

技术标签:

【中文标题】如何为我的 GIF tilesheet 制作动画(OpenGL、DevIL、C++)【英文标题】:How to animate my GIF tilesheet (OpenGL, DevIL, C++) 【发布时间】:2016-05-21 13:40:39 【问题描述】:

我试图在我的窗口中设置一个 gif 动画,方法是让它滚动到我的 tilesheet 上的每一帧,但它目前只停留在一个帧上。我认为这是因为我没有限制 gif 上的 fps,但我不知道如何做到这一点。有人吗?

@max66 我正在尝试通过这样做来获得动画。我试图让它沿着纹理(这是一个精灵图块表)的 y 轴向下移动,到目前为止它在没有 if 语句的情况下工作,但它在最后一帧冻结。

我的(新的)代码:

#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 gSamusSprites;

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( "SamusM.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( !gSamusSprites.loadTextureFromFile( "SamusG.png" ) )

    printf( "Unable to load texture!\n" );
    return false;


    while(scroll != 40)
    y += 214.f;
    scroll++;
    if(scroll == 40)
        scroll = 0;
    
 

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

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

gSamusSprites.addClipSprite( clip );

if( !gSamusSprites.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 );
gSamusSprites.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();

编辑:我只是尝试在 for 循环中调整 y 坐标值,但没有发生任何事情,所以我尝试删除 if 语句,但仍然没有。但是如果我调整文件顶部的 y 值,纹理就会改变。那么为什么我的循环没有增加我的 y 值呢?

【问题讨论】:

【参考方案1】:

我想是因为在你的for

for(int scroll; scroll > 40; scroll++)

你声明了scroll 变量,但你没有初始化它。

所以scroll 以一个可以大于 40 的未定义值开头。

解决方案(我想):初始化scroll

ps:对不起,我的英语不好。

--- 编辑 2016.05.23 ---

看看这段代码

    while(scroll != 40)
    y += 214.f;
    scroll++;
    if(scroll == 40)
        scroll = 0;
    


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

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

gSamusSprites.addClipSprite( clip );

如果scrool 以不同于40 的值到达while,则while 永远不会退出,您只会(永远)递增y

我想您的意图是为 while 的每次迭代调用 gSamusSprites.addClipSprite()(或类似函数)。

我想你的意图是只迭代循环 40 次并退出。

如果我的假设是正确的,您可以尝试类似 [警告:未测试]

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

for (scroll = 0; scroll < 40; ++scroll, clip.y += 214.f )
    gSamusSprites.addClipSprite( clip ); // or a different function?     

【讨论】:

我在滚动变量之后通过 = 0 初始化了它(愚蠢的错误),但没有任何改变。所以这让我回到了第一方。任何线索如何让它工作? @PochetTNT - 抱歉:我昨天没有仔细看。但是...如果您将scroll 初始化为0,则scroll &gt; 40 测试为假,并且for 的主体永远不会执行;你的意图是scroll &lt; 40?在这种情况下,if ( scroll &gt;= 40 ) scroll = 1; 永远不会被执行。但是如果for的测试是test &gt;= 40,当test == 40内部的if设置scroll = 1,那么for永远不会退出。真的:我不明白你的意图是什么for 好的,所以我通过重新安装 glew 解决了我的 while 循环崩溃问题(a ** 中的痛苦)。现在我正在执行相同的代码,但在一个 while 循环中。我的新问题是,当我将 if 语句添加到循环(for 或 while)时,它会使我的程序崩溃,但如果没有 if 语句,它就会卡在最后一帧。我试图通过使用循环来完成的是让它滚动我的“gif”,我把它变成了一个垂直的 tilesheet,所以它是动画的。 这就是我当前的循环代码while(scroll != 40) y += 214.f; scroll++; if(scroll == 40) scroll = 0; @PocketTNT - 但这(如果我没记错的话)是一个永无止境的循环。从零到 39 再到零,再到 39,再到零,等等。

以上是关于如何为我的 GIF tilesheet 制作动画(OpenGL、DevIL、C++)的主要内容,如果未能解决你的问题,请参考以下文章

如何为不受支持的客户端将 HTML 电子邮件中的 GIF 替换为不同的图像

IOS支持显示GIF动画图片吗? [复制]

如何为内容块制作动画?

如何为png图像制作动画

如何为熊猫时间序列制作动画?

如何为github上的项目添加gif效果图