使用C ++在SDL 2.0中渲染来自相同纹理的多个精灵

时间:2014-01-10 15:26:15

标签: c++ textures rendering sdl sprite

我正在尝试制作Puyo Puyo游戏。这是一个难题。这意味着许多相同的精灵将同时出现。我得渲染四种类型的精灵。但是,当第一个完成下降时,下一个精灵闪烁,游戏开始滞后。

我已经阅读过将堕落的精灵分组到一个纹理,所以它们作为单个纹理工作,我认为使用LockTexture可能会有效。但我不知道如何使用它。

这是我的代码:

//While application is running
while( !quit )
{
    //Get objects from list (Deque).
    puyo* p=list_puyo.at(c_list);
    p->move=true;
    getSpriteClip(p);
    //printf(c_list+": y:"+p.y);

    //Characters that haven't reached bottom continue to fall.
    if(p->move &&!p->bottom)
        fallingPuyo(p); //Every 512 miliseconds, the character will fall 32 pixels.

    //Handle events on queue
    while( SDL_PollEvent( &e ) != 0 )
    {
        //User requests quit
        if( e.type == SDL_QUIT )
        {
            quit = true;
        }

    }
    //Set texture based on current keystate


    const Uint8* currentKeyStates = SDL_GetKeyboardState( NULL );
    if(!p->bottom && p->move)
    {

        if( currentKeyStates[ SDL_SCANCODE_DOWN ] )
        {

            if(!collisionCheck(false,false,p))
            {
                pressedKey++;
                if(pressedKey>128)
                {
                    p->y+=32;
                    pressedKey=0;
                }
            }

        }
        else if( currentKeyStates[ SDL_SCANCODE_LEFT ] )
        {
            if(!collisionCheck(true,false,p))
            {
                pressedKey++;
                if(pressedKey>128)
                {
                    p->x-=32;
                    pressedKey=0;
                }
            }
        }
        else if( currentKeyStates[ SDL_SCANCODE_RIGHT ] )
        {
            if(!collisionCheck(false,true,p))
            {
                pressedKey++;
                if(pressedKey>128)
                {
                    p->x+=32;
                    pressedKey=0;
                }
            }
        }
    }
    //Clear screen
    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
    SDL_RenderClear( gRenderer );

    gBackgroundTexture.render(0,0); //window background

    gBoardTexture.render(SCREEN_WIDTH/4+30,0); //board background

    gSpriteSheetTexture.render( p->x, p->y, p->gSpriteClips); //puyos render

    //Update screen
    SDL_RenderPresent( gRenderer );

    //Return puyo to list
    list_puyo.at(c_list)=p;

    //Increment list counter by one.
    c_list++;

    //return counter to 0.
    if(c_list>=list_puyo.size())
        c_list=0;

}
}
}

1 个答案:

答案 0 :(得分:1)

//you want a "global" list of input, so you don't have to check only in input
bool keyLeftPressed = false;
bool keyRightPressed = false;
bool keyDownPressed = false;

//this controls how long before your player can move the puyo again
//so you don't have to do a hacky method in your keypressing code
int controlCooldown = 0;
while( !quit ) {
    //this little if makes your cooldown go back to zero slowly
    if(controlCooldown > 0) {
        controlCooldown--;
    }

    //Handle events on queue
    while( SDL_PollEvent( &e ) != 0 ) {
        //User requests quit
        if( e.type == SDL_QUIT ) {
            quit = true;
        } elsef if(e.type == SDL_KEYDOWN) { //all events (including keypress) go in the event loop
            if(e.key.keysym.sym == SDLK_DOWN) {
                keyDownPressed = true;
            } if(e.key.keysym.sym == SDLK_LEFT) {
                keyLeftPressed = true;
            } if(e.key.keysym.sym == SDLK_RIGHT) {
                keyRightPressed = true;
            }
        } else if(e.type == SDL_KEYUP) {//key release, set them back to false
            if(e.key.keysym.sym == SDLK_DOWN) {
                keyDownPressed = false;
            } if(e.key.keysym.sym == SDLK_LEFT) {
                keyLeftPressed = false;
            } if(e.key.keysym.sym == SDLK_RIGHT) {
                keyRightPressed = false;
            }
        }
    }

    //you need to iterate every puyo every frame, not just one
    for(unsigned int i = 0; i < list_puyo.size(); i++) {
        puyo* p = list_puyo.at(i);
        if(p->move &&!p->bottom) {
            fallingPuyo(p);
        }
        if(controlCooldown >= 0) {
            if(keyLeftPressed) {
                p->x-=32;
                controlCooldown = 128;
            } else if(keyRightPressed) {
                p->x+=32;
                controlCooldown = 128;
            } else if(keyDownPressed) {
                p->y+=32;
                controlCooldown = 128;
            }
            //if any key was pressed, they now have to wait 128 more cycles before it moves again
        }
        //i'm not sure how you want to render each puyo, or if you are already doing it
        renderPuyo(p);
    }


    //Clear screen
    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
    SDL_RenderClear( gRenderer );

    gBackgroundTexture.render(0,0); //window background

    gBoardTexture.render(SCREEN_WIDTH/4+30,0); //board background

    gSpriteSheetTexture.render( p->x, p->y, p->gSpriteClips); //puyos render

    //Update screen
    SDL_RenderPresent( gRenderer );

}
}
}

好的,我会告诉你一个主要的变化:

  • Puyo逻辑(你的问题的解决方案)
    所有的puy都会在每帧中迭代,而不是每帧一次。这就是他们之前闪烁的原因。这也解决了他们采取的任何行动。
  • 用于移动puyo的冷却时间 每次按下一个键时,它不是递增一个值,而是每增加一个滴答,直到达到0。这样更好,因为如果用户轻轻敲击一个键然后快速释放,那么puyo移动的可能性非常小。这解决了问题,通过将其设置为零,然后被动地递减每一帧,而不仅仅是在按下键时
  • 事件队列 我之前不知道你在做什么,涉及到键击,但现在每个感兴趣的键都有一个简单的布尔值。这有两个好处:
    1. 您可以将逻辑代码放在任何地方,而不仅仅是输入部分
    2. 您可以进行连续的密钥检查,而不仅仅是按下它。如果您需要来检查点击,只需添加旧代码

当然,我只是根据这个片段解释你的代码所做的事情。如果我有什么不妥,不要这样做。希望这有帮助!