SDL 1.2必须按两次键才能使事件生效

时间:2014-12-24 14:30:11

标签: c sdl sdl-1.2

为了抓住事件,我进入了我的主循环。如果玩家输入“1”,那么我调用函数play(),其中包含一个事件循环(用于移动等...)。 我真的不明白为什么,但我必须按两次ESCAPE才能离开游戏,而其他关键只是看起来没有被认出来。 如果我将循环删除到我的主程序中,那么一切正常。

这是我在主要的循环:

while(continuer)
    {
        SDL_WaitEvent(&event);

        switch(event.type)
        {
            case SDL_QUIT:
                continuer = 0;
                break;

            case SDL_KEYDOWN:
                switch(event.key.keysym.sym)
                {
                    case SDLK_ESCAPE:
                        continuer = 0;
                        break;

                    case SDLK_KP1:
                        play(screen);
                        break;
                }
                break;
        }
    } 

这是我的功能(她还在进行中,所以如果看起来像A LOOOOT愚蠢,请不要感到震惊:D)

void play(SDL_Surface* screen)
{
    int i=0, j=0, continuer=1;
    int elements[LARGEUR_MAP][HAUTEUR_MAP];
    char object =' ';
    FILE* level = NULL;
    SDL_Surface *lvl[LARGEUR_MAP][HAUTEUR_MAP],*mario[4];
    SDL_Rect posElem, posMario;
    SDL_Event event;

screen = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE,32,SDL_HWSURFACE | SDL_DOUBLEBUF);
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format,255,255,255));

mario[HAUT] = IMG_Load("images\\mario_haut.gif");
mario[DROITE] = IMG_Load("images\\mario_droite.gif");
mario[BAS] = IMG_Load("images\\mario_bas.gif");
mario[GAUCHE] = IMG_Load("images\\mario_gauche.gif");

//Ouverture du fichier contenant les infos du niveau
level = fopen("lvl.txt","r");

if(level == NULL)
{
    fprintf(stderr,"Erreur lors de l'ouverture du fichier");
    exit(EXIT_FAILURE);
}

//Boucle pour lire le fichier et placer les éléments du décor
for(j=0;j<HAUTEUR_MAP;j++)
{
    for(i=0;i<LARGEUR_MAP;i++)
    {
        object = fgetc(level);
        if(object == '\n')
            object = fgetc(level);
        switch(object)
        {
            case 'm':
                lvl[i][j] = IMG_Load("images\\mur.jpg");
                elements[i][j] = MUR;
                posElem.x = i*TAILLE_BLOC;
                posElem.y = j*TAILLE_BLOC;
                SDL_BlitSurface(lvl[i][j], NULL, screen, &posElem);
                break;

            case 'o':
                lvl[i][j] = IMG_Load("images\\objectif.png");
                elements[i][j] = OBJECTIF;
                posElem.x = i*TAILLE_BLOC;
                posElem.y = j*TAILLE_BLOC;
                SDL_BlitSurface(lvl[i][j], NULL, screen, &posElem);
                break;

            case 'c':
                lvl[i][j] = IMG_Load("images\\caisse.jpg");
                elements[i][j] = CAISSE;
                posElem.x = i*TAILLE_BLOC;
                posElem.y = j*TAILLE_BLOC;
                SDL_BlitSurface(lvl[i][j], NULL, screen, &posElem);
                break;

            case 'M':
                lvl[i][j] = IMG_Load("images\\mario_bas.gif");
                elements[i][j] = MARIO;
                posElem.x = i*TAILLE_BLOC;
                posElem.y = j*TAILLE_BLOC;
                SDL_BlitSurface(lvl[i][j], NULL, screen, &posElem);
                break;

            default :
                elements[i][j] = VIDE;
                break;
        }
    }
}

SDL_Flip(screen);
fclose(level);

//Code à l'arrache... Je met en dur la position de Mario, on verra plus tard pour l'automatisation ~~
i = 5;
j = 2;
posMario.x = i * TAILLE_BLOC;
posMario.y = j * TAILLE_BLOC;

while(continuer)
{
    SDL_WaitEvent(&event);

    switch(event.type)
    {
        case SDL_QUIT:
            continuer = 0;
            break;

        case SDL_KEYDOWN:
            switch(event.key.keysym.sym)
            {
                case SDLK_UP:
                    continuer = 0;
                    if(elements[i-1][j] != MUR && elements[i-1][j] != CAISSE_OK && i != 0)
                    {
                        posMario.x = (i-1)*TAILLE_BLOC;
                        posMario.y = j*TAILLE_BLOC;

                        if(elements[i-1][j] == CAISSE && elements[i-2][j] != MUR && elements[i-2][j] != CAISSE && elements[i-2][j] != CAISSE_OK && (i-2)>0)
                        {
                            SDL_FillRect(lvl[i][j], NULL, SDL_MapRGB(screen->format,255,255,255));
                            SDL_BlitSurface(mario[HAUT],NULL,screen,&posMario);
                            SDL_Flip(screen);
                        }
                    }
                    break;

                case SDLK_ESCAPE:
                    continuer = 0;
                    break;
            }
    }
}
}

1 个答案:

答案 0 :(得分:4)

据我所知,你有两个(嵌套的)事件循环,都使用他们的本地&#39;继续者&#39;变量。当你进入内部循环时,按下escape将从那个循环中移出到外部循环:你需要再次按esc从该循环中出来。

根据您的需要,可以采用一种可能的快速解决方案。从play()返回true或false以指示玩家是否想要退出游戏。就个人而言,我认为使嵌套事件循环表现得很好可能会很麻烦(当它们很大而且很深)时,但遗憾的是在很多情况下你无法避免它们。如果可以的话,要小心它们。