C++, SDL2, OpenGL - Слишком лагучая анимация!

#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_image.h>
#include <string>
using namespace std;

class Timer{
public:
    void start(){
        if(!isStarted)
            isStarted=true;
    }

    float inMilliseconds(){
        if(isStarted){
            if(!canRestart)
                canRestart=true;
            milliseconds=(float)(SDL_GetTicks()-rTime)/1000;
        }
        return milliseconds;
    }

    void restart(){
        if(canRestart){
            canRestart=false;
            rTime=SDL_GetTicks();
        }
    }

private:
    bool isStarted=false;

    bool canRestart=false;

    float milliseconds=0;

    float rTime=0;
};

Timer timer;

SDL_Window *window;
SDL_Event event;

SDL_Surface *texture;

GLuint textureID=0;
int mode;

float width=0, height=0;

float x=0, y=0;

const Uint8 *key=SDL_GetKeyboardState(0);

void movement(){
    if(key[SDL_SCANCODE_D])
        x+=0.04;
    if(key[SDL_SCANCODE_A])
        x-=0.04;
    if(key[SDL_SCANCODE_W])
        y-=0.04;
    if(key[SDL_SCANCODE_S])
        y+=0.04;
}

void loadTexture(string path){
    texture=IMG_Load(path.c_str());

    width=texture->w;
    height=texture->h;

    if(texture->format->BitsPerPixel>=4)
        mode=GL_RGBA;
    else
        mode=GL_RGB;

    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);

    glTexImage2D(GL_TEXTURE_2D, 0, mode, texture->w, 
        texture->h, 0, mode, GL_UNSIGNED_BYTE, texture->pixels);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    width*=4; height*=4;
}

void displayTexture(){
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, 800, 800, 0, -10, 10);

    glPushMatrix();
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glTranslatef(x, y, 0);
    glBegin(GL_POLYGON);
        glTexCoord2f(0, 0); glVertex2i(0, 0);
        glTexCoord2f(1, 0); glVertex2i(width, 0);
        glTexCoord2f(1, 1); glVertex2i(width, height);
        glTexCoord2f(0, 1); glVertex2i(0, height);
    glEnd();

    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();
}

int main(){
    window=SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, 
        SDL_WINDOWPOS_CENTERED, 800, 800, SDL_WINDOW_OPENGL);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    SDL_GLContext context=SDL_GL_CreateContext(window);

    SDL_GL_SetSwapInterval(SDL_FALSE);

    loadTexture("1.png");

    timer.start();

    while(window!=NULL){
        while(SDL_PollEvent(&event)){
            if(event.type==SDL_QUIT)
                window=NULL;
            if(event.key.keysym.scancode==SDL_SCANCODE_ESCAPE)
                window=NULL;
        }

        movement();

        if(timer.inMilliseconds()>=0.1)
            loadTexture("1.png");
        if(timer.inMilliseconds()>=0.4){
            loadTexture("2.png");
            timer.restart();
        }

        displayTexture();

        SDL_GL_SwapWindow(window);
    }
}

Как исправить лаги при движений?


Ответы (1 шт):

Автор решения: Red Bull

HolyBlackCat всё заработало, спасибо!

#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_image.h>
#include <string>
using namespace std;

class Timer{
public:
    void start(){
        if(!isStarted)
            isStarted=true;
    }

    float inMilliseconds(){
        if(isStarted){
            if(!canRestart)
                canRestart=true;
            milliseconds=(float)(SDL_GetTicks()-rTime)/1000;
        }
        return milliseconds;
    }

    void restart(){
        if(canRestart){
            canRestart=false;
            rTime=SDL_GetTicks();
        }
    }

private:
    bool isStarted=false;

    bool canRestart=false;

    float milliseconds=0;

    float rTime=0;
};

Timer timer;

SDL_Window *window;
SDL_Event event;

GLuint *textures;

float x=0, y=0;

int mode=GL_RGB;

const Uint8 *key=SDL_GetKeyboardState(0);

int textureCount=0;

void movement(){
    if(key[SDL_SCANCODE_D])
        x+=0.04;
    if(key[SDL_SCANCODE_A])
        x-=0.04;
    if(key[SDL_SCANCODE_W])
        y-=0.04;
    if(key[SDL_SCANCODE_S])
        y+=0.04;
}

SDL_Surface *image;

void loadTexture(GLuint texture, string filename){
    image=IMG_Load(filename.c_str());

    if(image->format->BitsPerPixel>=4)
        mode=GL_RGBA;
    else
        mode=GL_RGB;

    glBindTexture(GL_TEXTURE_2D, texture);

    glTexImage2D(GL_TEXTURE_2D, 0, mode, image->w, 
        image->h, 0, mode, GL_UNSIGNED_BYTE, image->pixels);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}

int id=0;

void showTexture(int a){
    id=a;
}

void displayTexture(){
    glPushMatrix();
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glTranslatef(x, y, 0);
    glBindTexture(GL_TEXTURE_2D, textures[id]);
    glBegin(GL_POLYGON);
        glNormal3f(0,1,0);
        glTexCoord2f(0, 0); glVertex2i(0, 0);
        glTexCoord2f(1, 0); glVertex2i(image->w*4, 0);
        glTexCoord2f(1, 1); glVertex2i(image->w*4, image->h*4);
        glTexCoord2f(0, 1); glVertex2i(0, image->h*4);
    glEnd();

    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();
}

int main(){
    window=SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, 
        SDL_WINDOWPOS_CENTERED, 800, 800, SDL_WINDOW_OPENGL);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    SDL_GLContext glContext=SDL_GL_CreateContext(window);

    SDL_GL_SetSwapInterval(SDL_FALSE);

    textures = new GLuint[3]; 
    glGenTextures(3, textures);

    loadTexture(textures[0], "1.png");
    loadTexture(textures[1], "2.png");
    loadTexture(textures[2], "3.png");
    loadTexture(textures[3], "4.png");

    timer.start();

    while(window!=NULL){
        while(SDL_PollEvent(&event)){
            if(event.type==SDL_QUIT)
                window=NULL;
            if(event.key.keysym.scancode==SDL_SCANCODE_ESCAPE)
                window=NULL;
        }

        movement();

        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, 800, 800, 0, -10, 10);

        if(timer.inMilliseconds()>=0.1)
            showTexture(0);
        if(timer.inMilliseconds()>=0.2)
            showTexture(1);
        if(timer.inMilliseconds()>=0.3)
            showTexture(2);
        if(timer.inMilliseconds()>=0.4){
            showTexture(3);
            timer.restart();
        }

        displayTexture();

        SDL_GL_SwapWindow(window);
    }
}
→ Ссылка