Problemas com captura de teclas em aplicações usando SDL!

Iniciado por mhkgalvez, 27 de Janeiro de 2010, 20:30

tópico anterior - próximo tópico

mhkgalvez

Olá pessoal.

Esses dias comecei a aprender a usar a biblioteca SDL para aplicações gráficas. Gostei pis a princípio parece bem simples. Já montei até a estrutura de um jogo e consegui fazer movimentação da uma imagem, mas tenho duas perguntas.:

1- Quando se movimenta uma imagem continuamente em uma aplicação de janelas comuns, a imagem começa a ficar distorcida conforme se movimenta, ou tremer. Isso se dá ao fato de aplicações assim não terem um determinado sistema que, pelo que me lembro, já começa a desenhar a imagem antes mesmo do movimento anterior ser realizado, acho que é isso. Bibliotecas que são específicas para fazer jogos já vem com isso imbutido, como o sistema XNA da Microsoft por exemplo; aliás um excelente sistema.

O problema é que quando movimento minha imagem na biblioteca SDL percebo que a imagem dá umas tremidas constantes. Por que isso acontece? E como resolver?

2- Quando detecto os eventos de teclado, a SDL não me fornece uma opção "KeyPressed" como no XNA por exemplo. Isso impede que eu realize movimentos contínuos na diagonal, por exemplo, além dos movimentos ficarem lentos, pois em tenho que soltar uma tecla para usar outra, etc. Enfim, nada pior pra um jogo.

Como resolvo esta situação usando a biblioteca SDL?

Abaixo segue meu script base:

Cabeçalho chamado 'game.h':
Citar#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

class Game
{
    public:
        // Construtor
        Game();
        // Método que inicializará componentes
        void Initialize();
        // Método que atualizará os componentes
        void Update();
        // Método que desenhará os componentes na tela
        void Draw();
        // Método que destruirá componentes desnecessários
        void Destroy();
};

#endif // GAME_H_INCLUDED

Programa principal chamado 'main.cpp':
Citar#include "SDL/SDL.h"
#include "cstdlib"
#include "cstdio"
#include "iostream"
#include "game.h";

using namespace std;

SDL_Surface *tela;
SDL_Surface *imagem;
SDL_Rect rect;
SDL_Event evento;
SDL_Event evento2;
//Novo Jogo
Game jogo;

int main(void)
{
   cout << "Iniciando Biblioteca SDL!" << endl;

    // Inicia a biblioteca SDL
   if (SDL_Init(SDL_INIT_VIDEO) == -1)
   {
      cout << "Houve um problema ao carregar a biblioteca SDL.\nErro: " << SDL_GetError() << endl;
      exit(-1);
   }

   cout << "Bilioteca carregada com sucesso!" << endl;
   cout << "Iniciando janela." << endl;

    // Seleciona nome da janela
    SDL_WM_SetCaption("Nome do Jogo", NULL);

    // Cria a janela e relaciona ela ao ponteiro screen e inicia o vídeo em resolução 640X480 com 16 dpi de qualidade
    tela = SDL_SetVideoMode(1360, 768, 24, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN );

    // Caso ele não consiga usar este modo de vídeo
    if (tela == NULL)
    {
      cout << "Impossível trocar modo de vídeo. Erro: \n" << SDL_GetError() << endl;
      exit(-1);
    }

    // Atualiza tela
    SDL_UpdateRect(tela, 0, 0, 1360,768 );

    // Começa a carregar componentes do jogo
    jogo.Initialize();

    cout << "Janela inicializada" << endl;
    // Loop principal
    // Cria o laço de verificação
    char fim = 0;
    while(fim == 0)
   {
        if (SDL_PollEvent(&evento))
        {
            if (evento.type == SDL_KEYDOWN)
            {
                if (evento.key.keysym.sym == SDLK_ESCAPE)
                {
                    break;
                }
            }
        }
        if (SDL_PollEvent(&evento2))
        {
            if (evento2.type == SDL_KEYDOWN)
            {
                if (evento2.key.keysym.sym == SDLK_ESCAPE)
                {
                    break;
                }
            }
        }
        else
        {
            // Delay para não utilizar 100% do processamento
            //SDL_Delay(10);
        }
        jogo.Update();
        jogo.Draw();
   }

    // Destrói componentes da memória
    jogo.Destroy();

    // Descarrega a dll de video da memória
    cout << "Descarregando DLL de vídeo da memória do sistema." << endl;
    SDL_QUIT;
   return 0;
}

Game::Game()
{
}

void Game::Initialize()
{
    // Carrega arquivo
    imagem = SDL_LoadBMP("logo.bmp");

    // Centraliza a imagem no centro da tela
    rect.x = (tela->w - imagem->w) / 2;
    rect.y = (tela->h - imagem->h) / 2;
}

void Game::Update()
{
    if (evento.type == SDL_KEYDOWN || evento2.type == SDL_KEYDOWN)
    {
        if (evento.key.keysym.sym == SDLK_UP)
        {
            rect.y-=2;
        }
        if (evento2.key.keysym.sym == SDLK_UP)
        {
            rect.y-=2;
        }
        if (evento.key.keysym.sym == SDLK_DOWN)
        {
            rect.y+=2;
        }
        if (evento2.key.keysym.sym == SDLK_DOWN)
        {
            rect.y+=2;
        }
        if (evento.key.keysym.sym == SDLK_LEFT)
        {
            rect.x-=2;
        }
        if (evento2.key.keysym.sym == SDLK_LEFT)
        {
            rect.x-=2;
        }
        if (evento.key.keysym.sym == SDLK_RIGHT)
        {
            rect.x+=2;
        }
        if (evento2.key.keysym.sym == SDLK_RIGHT)
        {
            rect.x+=2;
        }
    }
    // Atualiza toda a tela
    SDL_UpdateRect(tela, 0,0,0,0);
}

void Game::Draw()
{
    // Verifica erro
    if (imagem == NULL)
    {
        cout << "Imposível carregar o arquivo. Erro:\n" << SDL_GetError() << endl;
    }
    else
    {
        // DRAWING STARTS HERE

        // Limpa tela
        SDL_FillRect(tela, 0, SDL_MapRGB(tela->format, 0, 0, 0));

        // Coloca a imagem na tela
        if (SDL_BlitSurface(imagem, 0, tela, &rect) < 0)
        {
            cout << "Erro no BlitSurface: " << SDL_GetError() << endl;
            exit(-1);
        }
        // DRAWING ENDS HERE
    }
}

void Game::Destroy()
{
    // Desaloca a imagem
    SDL_FreeSurface(imagem);
}

Linguagem usada: C++ :-*
"A quem vencer, eu o farei coluna no templo do meu Deus, e dele nunca sairá; e escreverei sobre ele o nome do meu Deus, e o nome da cidade do meu Deus, a nova Jerusalém, que desce do céu, do meu Deus, e também o meu novo nome."