-1

我正在处理的程序有问题。有时,它会冻结。没有错误或任何东西。

该游戏是一款多人游戏,您可以在其中驾驶一艘船。其他玩家和道具的照片会根据您的位置进出视野。在大多数情况下,它工作得很好,但在某些情况下,它会锁定。

我已经追踪到它何时将一个表面 BLIT 到另一个表面上。(SDL_BlitSurface)。

如果我注释掉它 blits (SDL_BlitSurface) 的单行代码,并用一个简单的圆圈替换图形,它在任何情况下都不会冻结。但是,注释掉圆圈并再次用blitting图形替换它,它会随机冻结。令人沮丧的是,有时会,有时不会。有时图形会在屏幕上停留片刻然后冻结,有时它会在它出现的那一刻冻结。有时,它根本不会冻结。我根本无法追踪到任何特别的事情。

我有大量的代码可以检查 NULL 表面,但似乎并没有阻止它。我还将它设置为将有关所有图形的信息输出到文件(例如宽度、高度、内存中的位置、x、y 等),并且没有什么不寻常的。

我的主要问题是,表面会导致 SDL_BlitSurface 冻结怎么办?我还可以为表面添加哪些其他检查,以确保它不会尝试涂抹坏表面?

代码太长无法列出,但它是如何工作的:

class Player
{
    Player();

    int x;
    int y;
    int xvel;
    int yvel;
    SDL_Surface *DrawScreen;
    SDL_Surface *ShipPic;

    void check_player_dist();
    void check_powerup_dist();
    void update();
};    

class PowerUp
{
    int x;
    int y;
    int type;
    SDL_Surface *Powerup_Pic;
};

Player::Player()
{
    Apply_Surface(0, 0, PlayerShipPics, ShipPic);
}

Player::Update(Player p[], PowerUp pu[])
{
    x += xvel;
    y += yvel;

    for (int i = 0; i < Num_Players; i++)
    {
        if (check_on_screen(p[i].x, p[i].y) == true)
        {
            Apply_Surface(x - p[i].x, y - p[i].y, p[i].ShipPic, DrawScreen);
        }
    }

    for (int i = 0; i < Num_PowerUps; i++)
    {
        if (check_on_screen(pu[i].x, pu[i].y) == true)
        {
            Apply_Surface(x - pu[i].x, y - pu[i].y, pu[i].Pic, DrawScreen);
        }
    }
}


int main()
{
    SDL_Surface *Screen;
    Player players[4];
    PowerUp powerups[200];
    Num_Players = 4;
    Num_PowerUps = 200;

    while (quit == false)
    {
        for (int i = 0; i < Num_Players; i++)
        {
            players[i].update(players, powerups);
            switch (i)
            {
                case 0: ScreenX = 0; ScreenY = 0; break;
                case 1: ScreenX = ScreenWid / 2; ScreenY = 0; break;
                case 2: ScreenX = 0; ScreenY = ScreenHigh / 2; break;
                case 3: ScreenX = ScreenWid / 2; ScreenY = ScreenHigh / 2; break;
            }
            Apply_Surface (ScreenX, ScreenY, players[i].DrawScreen, Screen);
        }

        if (SDL_Flip(Screen) == -1)
        {
            return -1;
        }
    }
}

void Apply_Surface (int x, int y, SDL_Surface* Source, SDL_Surface* Destination, SDL_Rect* Clip)
{
    SDL_Rect Offset;

    Offset.x = x;
    Offset.y = y;

    if ((Source != NULL) && (Destination != NULL))
    {
        SDL_BlitSurface (Source, Clip, Destination, &Offset );
    }
}

我注意到当两个或更多玩家彼此靠近并试图在他们的两个屏幕上绘制相同的加电时,它通常会冻结。但是再次......并非总是如此!

4

2 回答 2

1

嗯,我知道它是什么了。

我在游戏中使用了 SDL_GFX 库。许多图像是使用 rotozoomSurface() 创建的,它是 SDL_GFX 的一个函数。

结果发现其中有一个错误,在某些我不知道的情况下,它会创建一个糟糕的表面,该表面将在“大部分”时间工作,但在正确的条件下,会崩溃。例如,被放置在屏幕上的特定 x & y 坐标处。(不确定)。旋转/缩放的图像在大约 95% 的时间内都可以正常工作,因此很难确定问题所在。

解决方法是,在创建图像时,只需 SDL_BlitSurface() 在受控条件下将其放到另一个表面上,例如将其放置在坐标 (0, 0) 处。然后,删除旋转和缩放的表面,只使用新的“安全”表面。

之后效果很好。

希望这将帮助任何使用 SDL_GFX 并且无法弄清楚他们的程序为什么会崩溃的人。

例子:

前:

SDL_Surface *original = SDL_CreateRGBSurface(SDL_SWSURFACE, Ship_Width, Ship_Height, Screen_BPP, 0, 0, 0, 0);
Apply_Surface(0, 0, ShipsPic, original, &bounds);

SDL_Surface *finished = rotozoomSurface(original, pic_angle, zoom, SMOOTHING_ON);
SDL_FreeSurface(original);
return finished;

之后(固定):

SDL_Surface *original = SDL_CreateRGBSurface(SDL_SWSURFACE, Ship_Width, Ship_Height, Screen_BPP, 0, 0, 0, 0);
Apply_Surface(0, 0, ShipsPic, original, &bounds);

SDL_Surface *temp = rotozoomSurface(original, pic_angle, zoom, SMOOTHING_ON);
SDL_Surface *finished = SDL_CreateRGBSurface(SDL_SWSURFACE, temp->w, temp->h, Screen_BPP, 0, 0, 0, 0);

Apply_Surface(0, 0, temp, finished);
SDL_FreeSurface(temp);
SDL_FreeSurface(original);
return finished;

对于它的价值,Apply_Surface() 函数:

void Apply_Surface (int x, int y, SDL_Surface* Source, SDL_Surface* Destination, SDL_Rect* Clip)
{
    SDL_Rect Offset;

    Offset.x = x;
    Offset.y = y;

    if ((Source != NULL) && (Destination != NULL))
    {
        SDL_BlitSurface (Source, Clip, Destination, &Offset );
    }
}
于 2013-06-27T16:28:05.683 回答
0

没有足够的信息来弄清楚到底发生了什么。计算机“有时”不喜欢做事,他们要么做要么不做,所以这让我相信,也许有一些变量在做它不应该做的事情。

以防万一,您的 Apply_Surface() 函数是什么样的?我假设这就是您实际执行 blitting 的地方,如果您遇到问题的地方,那对于我们这些试图找出您的困境的人来说会很有用。

于 2013-06-20T01:27:27.010 回答