【问题标题】:Rendering several sprites from the same texture in SDL 2.0 with C++使用 C++ 在 SDL 2.0 中从同一纹理渲染多个精灵
【发布时间】:2014-01-10 15:26:14
【问题描述】:

我正在尝试制作 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;

}
}
}

【问题讨论】:

  • 等等,它只是在一个跌倒后才开始闪烁?还是在添加第二个之后?如果你没有双缓冲,你可能想要这样做,因为闪烁通常是没有双缓冲的症状。
  • 您是在为列表的一次迭代执行所有这些操作,还是我错误地解释了您的代码?
  • 不,@olevegard,如果列表计数器变得大于列表本身,会发生什么情况,计数器将返回零。我正在浏览列表中的所有对象。
  • @BWG,我如何使用双缓冲?
  • @ElAramu 好吧,您可能已经在使用双缓冲了。我没有使用 SDL 图形。但是我在您的代码中看到了其他一些奇怪的东西。例如,这整件事就是你的主循环。然而,每个循环你只能对一个 puyo 采取行动。然后,您将其“返回”到列表中。这是不必要的,因为p 是一个指针,而不是一个实例,所以返回它只会将列表中的指针设置回原来的样子。

标签: c++ textures rendering sdl sprite


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

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

【讨论】:

  • 非常感谢,@BWG。这很奇怪,因为在将代码发布到此处之前,我使用了一个循环来渲染所有 puyo 并且它开始滞后。但是,现在不行了。我使用了您的关键状态更改。现在它可以工作并且它不会闪烁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-14
  • 2019-06-09
  • 2014-10-28
相关资源
最近更新 更多