user6183967
user6183967

Reputation:

How to correctly detect key press and release in sdl2

My complete code -

#include <SDL.h>
#include <SDL_opengl.h>
#include <GL\GLU.h>
#include <fstream>

using namespace std;


int index = 0;
int speed = 0;
int frames = 0;
int lasttime = 0;
int mousex = 0;
int mousey = 0;
bool postRedraw = true;

int screenWidth = 640;
int screenHeight = 480;
float screenAspect = screenWidth/screenHeight;

bool init();
bool initGL();
void handleKeys( unsigned char key, int x, int y );
void update();
void render();
void close();
void Initialize();
void handleEvents();


ofstream logFile;

SDL_Window* gWindow = NULL;
bool isRunning = true;
SDL_GLContext gContext;
float xpos = 0.0;
float ypos = 0.0;
float zpos = 0.0;


void Initialize()
{
    gluPerspective(60.0f, screenAspect, 1.0, 400.0);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_NORMALIZE);
    glTranslatef(0.0f, 0.0f, -5.0f);
    glFrontFace(GL_CCW);
    glEnable(GL_LIGHT0);
}


void render()
{
    glTranslatef(xpos, ypos, zpos);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    glBegin(GL_TRIANGLES);
        glVertex3f(-1.0f,0.0f,-1.0f);
        glVertex3f(0.0f, 1.0f, -1.0f);
        glVertex3f(0.0f, 2.0f, -2.0f);
    glEnd();
    postRedraw = true;
}


void handleEvents()
{
    const Uint8* keystates = SDL_GetKeyboardState(NULL);
    if(keystates[SDL_GetScancodeFromKey(SDLK_w)])
    {
        zpos += 0.01;
    }
    if(keystates[SDL_GetScancodeFromKey(SDLK_s)])
    {
        zpos -= 0.01;
    } else {
    }
}

bool init()
{
    bool success = true;
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        logFile<<"SDL could not initialize! SDL Error: "<<SDL_GetError()<<endl;
        success = false;
    }
    else
    {
        SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
        SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
        gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screenWidth, screenHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
        if( gWindow == NULL )
        {
            logFile<<"Window could not be created! SDL Error: "<<SDL_GetError()<<endl;
            success = false;
        }
        else
        {
            gContext = SDL_GL_CreateContext( gWindow );
            if( gContext == NULL )
            {
                logFile<<"OpenGL context could not be created! SDL Error: "<<SDL_GetError()<<endl;
                success = false;
            }
            else
            {
                if( SDL_GL_SetSwapInterval( 1 ) < 0 )
                {
                    logFile<<"Warning: Unable to set VSync! SDL Error: "<<SDL_GetError()<<endl;
                }
                if( !initGL() )
                {
                    logFile<<"Unable to initialize OpenGL!"<<endl;
                    success = false;
                }
            }
        }
    }
    logFile.open("log.txt");
    if(logFile.is_open())
    {
        success = true;
    } else {
        success = false;
    }
    return success;
}

bool initGL()
{
    bool success = true;
    GLenum error = GL_NO_ERROR;
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    error = glGetError();
    if( error != GL_NO_ERROR )
    {
        logFile<<"Error initializing OpenGL! "<<gluErrorString( error )<<endl;
        success = false;
    }
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    error = glGetError();
    if( error != GL_NO_ERROR )
    {
        logFile<<"Error initializing OpenGL! "<<gluErrorString( error )<<endl;
        success = false;
    }
    glClearColor( 0.f, 0.f, 0.f, 1.f );
    error = glGetError();
    if( error != GL_NO_ERROR )
    {
        logFile<<"Error initializing OpenGL! "<<gluErrorString( error );
        success = false;
    }

    return success;
}


void close()
{
    logFile.close();
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;
    SDL_Quit();
}

int main( int argc, char* args[] )
{
    if( !init() )
    {
        logFile<<"Failed to initialize!"<<endl;
    }
    else
    {

        SDL_Event event;
        Initialize();
        lasttime = SDL_GetTicks();
        while(isRunning)
        {
            while( SDL_PollEvent( &event ) != 0 )
            {
                if(event.type == SDL_QUIT)
                {
                    isRunning = false;
                } else if(event.type == SDL_MOUSEMOTION) {
                    SDL_GetMouseState(&mousex, &mousey);
                } else if(event.type == SDL_MOUSEBUTTONDOWN) {
                    SDL_GetMouseState(&mousex, &mousey);
                } else if(event.type == SDL_MOUSEBUTTONUP) {
                    SDL_GetMouseState(&mousex, &mousey);
                }
            }
            handleEvents();
            if(postRedraw)
            {
                postRedraw = false;
                render();
                SDL_GL_SwapWindow( gWindow );
            }
            if((SDL_GetTicks()-lasttime)>=1000)
            {
                lasttime = SDL_GetTicks();
                speed = frames;
                logFile<<speed<<endl;
                frames = 0;
            } else {
                frames++;
            }
        }
    }

    close();

    return 0;
}

The above code is just for testing, the minimalistic code where I have problem is -

void handleEvents()
{
    const Uint8* keystates = SDL_GetKeyboardState(NULL);
    if(keystates[SDL_GetSancodeFromKey(SDLK_w)]) {
        zpos += 0.01;
    }
    if(keystates[SDL_GetScancodeFromKey(SDLK_s)])
    {
        zpos -= 0.01;
    } else {
    }
}

Expected: the trangle drawn will move forword/ backward while w/s key is pressed.

Output: the triangle keeps on moving in the desired direction even if the key was released.

Upvotes: 2

Views: 1164

Answers (1)

keltar
keltar

Reputation: 18409

You accumulate your matrix changes over time. glTranslatef modifies current matrix with translation. The next frame it modifies it again. And again, ....

You shoud reset matrix with glLoadIdentity() call. Be aware that it modifies currently selected matrix and will undo matrix changes you've made in Initialize (at least your glTranslatef here - perspective should go to GL_PROJECTION matrix, which you haven't done).

Upvotes: 3

Related Questions