2

我正在尝试为横向滚动游戏制作敌人产卵/移动系统。
应该发生的事情是敌人将产生并向右移动,直到它们与特定物体碰撞,然后它们将向相反方向移动。

我进行了研究并提出了一个问题来让我走到这一步:我创建了一个敌人类别,然后制作了一个可以添加更多敌人并设置他们个人产卵位置的列表。然后我创建了一个EnemyBlock类,这样我就可以设置各种碰撞对象的位置(在这种情况下,它们只是砖块)。

我遇到了一些麻烦
A. 让敌人在离开游戏屏幕时转身。
和 B. 为敌人和敌人块编写碰撞代码,就像我尝试Game1.cs Update在它下面的部分中编写碰撞代码foreach (Enemy enemy in enemies)一样,不会选择敌人块的矩形。如果这是有道理的。对不起,我对 XNA 代码很陌生。

Game1.cs代码

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    public Rectangle bounds;

    List<Enemy> Enemies = new List<Enemy>();
    List<EnemyBlock> Blocks = new List<EnemyBlock>();

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }


    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        base.Initialize();
    }


    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);

        Blocks.Add(new EnemyBlock(Content.Load<Texture2D>("02Brick"), new Vector2(50, 100)));
        Enemies.Add(new Enemy(Content.Load<Texture2D>("Mario_Sprite"), new Vector2(100, 100), new Vector2(1, 0)));
        Blocks.Add(new EnemyBlock(Content.Load<Texture2D>("02Brick"), new Vector2(500, 100)));
        Blocks.Add(new EnemyBlock(Content.Load<Texture2D>("02Brick"), new Vector2(50, 200)));
        Enemies.Add(new Enemy(Content.Load<Texture2D>("Mario_Sprite"), new Vector2(100, 200), new Vector2(1, 0)));
        Blocks.Add(new EnemyBlock(Content.Load<Texture2D>("02Brick"), new Vector2(400, 200)));

        foreach (Enemy enemy in Enemies)
        {
           enemy.bounds = new Rectangle((int)(enemy.position.X - enemy.texture.Width), (int)(enemy.position.Y - enemy.texture.Height), enemy.texture.Width, enemy.texture.Height);
        }
        foreach (EnemyBlock block in Blocks)
        {
            block.bounds = new Rectangle((int)(block.position.X - block.texture.Width), (int)(block.position.Y - block.texture.Height), block.texture.Width, block.texture.Height);
        }

    }


    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }


    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        foreach (Enemy enemy in Enemies)
        {
            if (!GraphicsDevice.Viewport.Bounds.Contains(enemy.bounds))
            {
                enemy.velocity = -enemy.velocity;
                enemy.position += enemy.velocity;

            }

            else
            {

                enemy.position += enemy.velocity;

            }
        }

        base.Update(gameTime);
    }


    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin();
        foreach (Enemy enemy in Enemies)
        {
            spriteBatch.Draw(enemy.texture, enemy.position, Color.White);
        }
        foreach (EnemyBlock block in Blocks)
        {
            spriteBatch.Draw(block.texture, block.position, Color.White);
        }
        spriteBatch.End();

        base.Draw(gameTime);
    }
}
}

敌人等级代码

class Enemy
  {
      public Texture2D texture;
      public Rectangle bounds;
      public Vector2 position;
      public Vector2 velocity;

      public Enemy(Texture2D Texture, Vector2 Position, Vector2 Velocity)
      {
          texture = Texture;
          position = Position;
          velocity = Velocity;
      }
  }

EnemyBlock 类代码

class EnemyBlock
{
    public Texture2D texture;
    public Rectangle bounds;
    public Vector2 position;

    public EnemyBlock(Texture2D Texture, Vector2 Position)
    {
        texture = Texture;
        position = Position;
    }
}
4

2 回答 2

2

您的代码似乎结构和组织得很好。让您更容易找到您遇到的任何这些问题,感谢您并保持您的代码井井有条。这是一个好习惯,它使更大的项目更容易。

无论如何,我想我可能有你的问题的答案。

你的矩形没有被拾取的原因是你正在为你的敌人和你的加载内容方法中的块初始化矩形。

这很好,只是您似乎没有更新矩形的位置。尽管您检查与边界矩形的碰撞,但您会更新敌人和方块的速度和位置。

这意味着您的敌人将能够离开屏幕并穿过对象,因为您的绘图位置已经移动,但矩形并不意味着它不会检测到碰撞。

我相信其他问题是指定矩形位置。我相信你的代码可能有点不对劲,但如果它工作正常,那就离开它。但是,如果碰撞检测有点偏离,请尝试以下操作。你的代码

enemy.bounds = new Rectangle((int)(enemy.position.X - enemy.texture.Width), (int)(enemy.position.Y - enemy.texture.Height), enemy.texture.Width, enemy.texture.Height);

应该看起来像

enemy.bounds = new Rectangle(enemy.position.X, enemy.position.Y, enemy.texture.Width, enemy.texture.Height);

根据您绘制图像的方式。

矩形的构造函数指定左上角的 x、y 位置和矩形的宽度/高度。Rectangle r = new Rectangle(100, 100, 200, 200) 创建一个宽 100、100 和 200 高 200 的矩形。

这将与您绘制敌人和方块的方式相匹配。

最后,碰撞代码相当简单:

foreach(Enemy enemy in Enemies)
{
  foreach(EnemyBlock block in Blocks)
  {
    if(enemy.bounds.Contains(block.bounds))
    {
      //what to do on collision
    }
  }
}

我希望这一切都是正确的并有所帮助。

于 2013-05-27T11:50:55.680 回答
0

无论如何,我对XNA并不精通,请尝试删除否定,因为代码看起来总是会在不在视口边缘时反转速度

 if (GraphicsDevice.Viewport.Bounds.Contains(enemy.bounds))
 {
     enemy.velocity *= -1;
 }
     enemy.position += enemy.velocity;

这样,敌人的速度只有在到达边界时才会反转。无需添加 else 语句,因为敌人总是在移动。

至于与敌人块的碰撞,这里有一个来自 MSDN 的关于制作像马里奥这样的 2D 横向滚动游戏的好教程。点击这里

在本教程中,所有内容都被视为 2d 数组地图上的瓦片对象,并且在更新时,它会检查敌人当前站立的阵列瓦片(敌人的位置)

于 2013-05-27T11:26:24.247 回答