如何拍摄激光?

时间:2016-02-04 02:12:01

标签: c struct sdl

我一直在学习C,并且正在尝试使用SDL来稍微改变一下。我想制作一个简单的太空射击游戏,其中空格键会让玩家的小船发射激光。

我目前关于它如何工作的思考过程将会有一个“激光”结构,它包含精灵表面和精灵矩形。

struct Laser {
    SDL_Surface *sprite;
    SDL_Rect rcSprite;
};

现在我需要一个能够创建“激光”结构的功能。它将分配内存,加载.BMP精灵图像并设置激光的起始位置。然后它将返回一个指向新创建的结构的指针。

struct Laser *fireLaser(char *sprite, int x, int y) {
    struct Laser *l = malloc(sizeof(struct Laser));
    assert(l != NULL);

    l->sprite = loadImage(sprite);
    l->rcSprite.x = x;
    l->rcSprite.y = y;

    return l;
}

现在的想法是在按下空格键时让激光射击。按照我认为这将起作用,这意味着需要为每次激光射击调用“fireLaser”函​​数。

if(keystate[SDLK_SPACE]) {
    lasers[i] = fireLaser("laser.bmp", player->rcSprite.x, player->rcSprite.y);
    drawLaser(lasers[i]);
    i += 1;
}

上面的代码将调用“drawLaser”函​​数,将新创建的Laser结构传递给它。

void drawLaser(struct Laser *laser) {
    while(laser->rcSprite.y > 0) {
        SDL_BlitSurface(laser->sprite, NULL, screen, &laser->rcSprite);
        laser->rcSprite.y -= 1;
    }
}

当我运行这个时,我期望发生的是我将按住空格键,并且因为没有频率的火,所以将从船上升起稳定的流。

代码编译,但当我运行它并按空格键时,会绘制一个预测的直白色,但程序崩溃(分段错误)!我发现(大多数是偶然的)如果我重新编写代码以在构造结构后将我的索引变量“ i ”设置回0(如下所示),程序将不会崩溃。 / p>

if(keystate[SDLK_SPACE]) {
    i = 0;
    lasers[i] = fireLaser("laser.bmp", player->rcSprite.x, player->rcSprite.y);
    drawLaser(lasers[i]);
    i += 1;
}

现在我在屏幕上垂直绘制了一条长长的白线。

我确信这可能不是一个非常好的方式,但我开始沿着这条路走下去,我正试着看透它!我现在的问题是,为什么我需要重置“ i ”变量,否则程序会崩溃?此外,我不得不问这是否是完成发射激光的有效方法。我是在正确的道路上,还是应该停下来重新评估?

1 个答案:

答案 0 :(得分:4)

虽然我无法给出准确的答案,因为我无法知道整个代码,但我可以解释它应该如何工作以及你与正常方法的区别。

正常的游戏循环就是这样的:

while (!exiting) {
  render();
  logic();
  events();
}

现在,render()应该绘制内容,logic()应移动内容,events()应轮询外部输入(例如键盘)并相应地修改内容。

在您的代码中,您正在代码的events()部分绘制激光。这是不正确的,你是混合的东西。一个好的设计就像是:

static size_t MAX_LASERS = 50;
static size_t laserCount;
static laser* lasers;

void setup()
{
  lasers = calloc(MAX_LASERS, sizeof(laser));
  laserCount = 0;
}

void draw()
{
  for (int i = 0; i < laserCount; ++i)
    drawLaser(lasers[i]);
}

void logic()
{
  for (int i = 0; i < laserCount; ++i)
  {
    moveLaser(lasers[i]);
  }

  for (int i = 0; i < laserCount; ++i)
  {
    if (outsideScreen(lasers[i])
      removeLaser(lasers[i])
  }
}

void events() 
{
  ...
  if(keystate[SDLK_SPACE]) {
    if (laserCount < MAX_LASERS)
      laser[laserCount++] = generateLaser(...);
  }
}