太空入侵者粘在墙上

本文关键字:入侵者 太空 | 更新日期: 2023-09-27 18:09:05

所以我必须为学校开发一款XNA游戏,我认为《太空入侵者》是个不错的选择。但现在我被一个问题缠住了。我有一个List,里面装满了另一个班的"外星人"。它每秒钟向右移动20像素,我希望它在触摸屏幕右侧时下降(不是问题)。但我想让它一碰到墙就朝相反的方向(向左)移动。问题就在这里。一旦它接触到墙壁,它仍然移动20px一次,改变方向,移动20px后再次改变方向。这一直在重复。那么问题在哪里呢?我认为它必须提前检查是否有一个外星人触摸屏幕,但不知道如何完成,并认为也许你们中的一个可以帮助我,因为这是非常令人沮丧的!

我包含了更新方法

if (xPos % step == 0)
{
   if (!isDescending)
   {
      for (int k = 0; k < sprites.Count; k++)
      {
         Sprite sprite = sprites[k];
         if (touchedRight) sprite.position.X += step;
         else sprite.position.X -= step;
      }
      for (int k = 0; k < sprites.Count; k++)
      {
         Sprite sprite = sprites[k];
         bool hitLeft = sprite.position.X == 0;
         bool hitRight = sprite.rect.Right == screenWidth;
         if ((hitLeft) || (hitRight))
         {
            touchedRight = !touchedRight;
            isDescending = true;
         }
      }
   }
   else
   {
      isDescending = false;
      for (int k = 0; k < sprites.Count; k++)
      {
         sprites[k].position.Y += sprites[k].rect.Height;
      }
   }
}
// CheckCollision(alienBounds, k-1);
// sprite.rect = new Rectangle((int)sprite.position.X, (int)sprite.position.Y, 20, 20);
// alienBounds = sprite.rect;
xPos += 1;

太空入侵者粘在墙上

这是错误的:

if ((hitLeft) || (hitRight))

右移时,只关心hitRight。当向左移动时,你只关心hitLeft

所以尝试

if (touchedRight? hitLeft: hitRight)

这也将修复多个外星人可以同时撞墙的问题。

我不确定,但我相信在《太空入侵者》中,如果你杀死除了最左边的所有列,它在切换方向之前不会完全移动到屏幕的右侧。

所以我建议你创建一个Sprite的衍生品,名为Invader:

class Invader : Sprite
{
    readonly float distanceFromCenterHorizontal;
    public Invader(float distanceFromCenterHorizontal)
    {
        this.distanceFromCenterHorizontal= distanceFromCenterHorizontal;
    }
    public void UpdatePosition(Point center)
    {
        this.Position.X = center.X + distanceFromCenterHorizontal;
        this.Position.Y = center.Y;
    }
}

// global variables:
Point center = ....
bool moveLeft = false;
void createInvaders()
{
    int invaderWidth = 20; // whatever your value is
    float columnCenter = ((float) columnMax) / 2 * invaderWidth;
    for(var column = 0; column < columnMax ; column++)
    {
        float invaderX = (column * invaderWidth);
        float distanceFromCenterHorizontal = invaderX - columnCenter;
        for(var row = 0; row < rowMax; row ++)
        {
            Invader invader = new Invader(distanceFromCenterHorizontal);
            invader.Position.Y = row * invaderHeight // Needs adjustment here!
        }
    }
}
void update()
{
    if(center.X == screenWidth) moveLeft = true;
    else if(center.X <= 0) moveLeft = false;
    center.X += moveLeft? -step : step;
    foreach(var invader in invaders) invader.UpdatePosition(center);
}

你想移动"中心点"和所有入侵者更新根据新的中心。

我不确定XNA是否使用双精度或浮点值,所以你可能需要调整这个。

你可以很容易地展开它来创建一些上下摆动

所以我创建了一个名为'bounds'的新矩形,它的宽度和外星人一样,移动的方式和外星人一样。让它工作起来!(一半)。它向右移动,直到它接触到右边,然后它向左移动,但一直向左移动,永远不会回到右边。那么这次我到底哪里出错了?

if (xPos % step == 0)
            {
                if (!isDescending)
                {
                    for (int k = 0; k < sprites.Count; k++)
                    {
                        Sprite sprite = sprites[k];
                        sprite.position.X += step;
                    }
                    if (bounds.Right == screenWidth || bounds.Left == 0)
                    {
                        touchedRight = !touchedRight;
                        step *= -1;
                    }
                    if (!touchedRight) bounds.X += step;
                    if (touchedRight) bounds.X -= step;
                    // for (int k = 0; k < sprites.Count; k++)
                    // {
                    //    Sprite sprite = sprites[k];
                    //    bool hitLeft = sprite.position.X == 0;
                    //    bool hitRight = sprite.rect.Right == screenWidth;
                    //    if ((hitLeft) || (hitRight))
                    //    {
                    //        touchedRight = !touchedRight;
                    //        isDescending = true;
                    //    }
                    // }
                }