0

为了捕捉事件,我在我的 main 中有一个循环。如果玩家输入“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;
        }
    } 

这是我的功能(她仍在进行中,所以如果它看起来很愚蠢,请不要感到震惊: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;
            }
    }
}
}
4

1 回答 1

4

据我了解,您有两个(嵌套的)事件循环,都使用它们的本地“连续”变量。当您进入内部循环时,按退出从那个循环到外部循环:您需要再次按 esc 才能退出该循环。

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

于 2014-12-24T15:51:50.050 回答