在平铺地图中移动平台

时间:2014-04-14 13:27:06

标签: c# object xna tile

我正在使用瓷砖地图,如果移动平台击中瓷砖,它应该朝另一个方向发展。我正在使用tilemap和platform的列表,这有助于保持整洁。

下面的图片显示了平台,它始终处于运动状态,当它与其中一个黑色圆圈发生碰撞时,它应该改变方向并以与它相反的方式前进。

Image of Platform and colliding tile

不幸的是我遇到了一个问题,我需要找到正确的平台,以便它会朝另一个方向发展。我在主类中创建了列表,并且不知道如何调用除main之外的另一个类中的列表。

问题:

如何调用一个包含多个对象的列表,这些列表位于不同的位置,位于不同的位置,并在主类中创建,以便我可以知道平台是否与磁贴碰撞?

简单地说,如何让平台与瓷砖碰撞?

以下是瓷砖地图必须经过使用和调用的过程:

要使tile图使用两个类,Block类和Game1类(主类)。

在Block类中,Texture,Position和BlockState(决定它将做什么)

    public Block(Texture2D Texture, Vector2 Position, int BlockState)
    {
        this.Texture = Texture;
        this.Position = Position;
        this.BlockState = BlockState;
    }

然后Block类将使用一个使用Player类的方法。

    public Player BlockCollision(Player player)
    { 
        Rectangle top = new Rectangle((int)Position.X + 5, (int)Position.Y - 10, Texture.Width - 10, 10);
        Rectangle bottom = new Rectangle((int)Position.X + 5, (int)Position.Y + Texture.Height, Texture.Width - 10, 10);
        Rectangle left = new Rectangle((int)Position.X - 10, (int)Position.Y + 5, 10, Texture.Height - 10);
        Rectangle right = new Rectangle((int)Position.X + Texture.Width, (int)Position.Y + 5, 10, Texture.Height - 10);

        if (BlockState == 1 || (BlockState == 2 && !player.goingUp))
        {
            if (top.Intersects(new Rectangle((int)player.Position.X, (int)player.Position.Y, player.Texture.Width, player.Texture.Height)))
            {
                if (player.Position.Y + player.Texture.Height > Position.Y && player.Position.Y + player.Texture.Height < Position.Y + Texture.Height / 2)
                {
                    player.Position.Y = player.ground = Position.Y - player.Texture.Height;
                    player.Velocity.Y = 0;
                    player.isJumping = false;
                    player.Time = 0;
                    player.botCollision = true;
                }
            }
        }

        return player;
    }

然后是Draw方法。

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(Texture, new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height), Color.White);
    }

然后我们转到主要类Game1。

我为块和平台创建了列表。

    List<Block> Blocks;
    List<MovingPlatform> Platforms;

使用char系统我创建地图。

    List<char[,]> Levels = new List<char[,]>();
    public int tileWidth, tileHeight;

然后在Initialize方法中,我调用Lists并创建地图。

    protected override void Initialize()
    {
        Blocks = new List<Block>();
        Platforms = new List<MovingPlatform>();

        char[,] Level1 = {{'.','.','#'},
                          {'.','.','#'},
                          {'.','.','#'}};

        Levels.Add(Level1);

        base.Initialize();
    }

然后调用void LoadLevel。

    void LoadLevel(int level)
    {
        Blocks.Clear();
        Platforms.Clear();

        player.Position = Vector2.Zero;

        tileWidth = Levels[level].GetLength(1);
        tileHeight = Levels[level].GetLength(0);

        Texture2D blockSpriteA = Content.Load<Texture2D>("blockA2");

        for (int x = 0; x < tileWidth; x++)
        {
            for (int y = 0; y < tileHeight; y++)
            {

                //Background
                Blocks.Add(new Block(background, new Vector2(x * 50, y * 50), 0));

                //Impassable Blocks
                if (Levels[level][y, x] == '#')
                {
                    Blocks.Add(new Block(blockSpriteA, new Vector2(x * 50, y * 50), 1));
                }

                //Vertical Moving Platform
                if (Levels[level][y, x] == '=')
                {
                    Platforms.Add(new MovingPlatform(platform, new Vector2(x * 50, y * 50), 3.0f, true));
                }

然后在更新中我打电话给列表。

        foreach (Block b in Blocks)
        {
            player = b.BlockCollision(player);
        }

        foreach (MovingPlatform m in Platforms)
        {
            player = m.BlockCollision(player);
            m.Update(gameTime);
        }

最后,Draw方法会调用它们。

        foreach (Block b in Blocks)
        {
            b.Draw(spriteBatch);
        }

        foreach (MovingPlatform m in Platforms)
        {
            m.Draw(spriteBatch);
        }

1 个答案:

答案 0 :(得分:1)

我想我理解你的问题,我不确定,但无论如何我都会冒险回答。

我认为你需要做的是将东西移出主游戏类。你有一个地图的概念和一堆属于地图(平台,块)的东西,所以将它封装在自己的类中是一个好主意,例如:

class Map
{
    public List<Block> Blocks;
    public List<MovingPlatform> Platforms;

    void LoadLevel(int level)
    {
        ///
    }
}

现在它使代码更清晰,但你现在还有一个可以传递的Map对象。

因此,例如,为了使MovingPlatform能够访问地图上的所有内容,您只需将对地图的引用作为参数传递给MovingPlatform构造函数,该构造函数将其保存到私有字段。例如:

class MovingPlatform
{
    Map _map;
    public MovingPlatform(Map map, Vector2 position, ...)
    {
        _map = map;
    }

    public void Update(GameTime gameTime)
    {
        //move platform
        //detect collision
        //have access to all the blocks and other platforms on map
        //_map.Blocks;
        //_map.Platforms;
    }
}

因此,在地图类LoadLevel()方法中,您将传入&#39;这个&#39;作为MovingPlatform构造函数的第一个参数:

class Map
{
    void LoadLevel(int level)
    {
        //Vertical Moving Platform
        if (Levels[level][y, x] == '=')
        {
            Platforms.Add(new MovingPlatform(this, ...));
        }
    }
}

您可以将其他地图特定内容(甚至是对播放器的引用?)添加到Map类中,MovingPlatforms将自动访问它们。

这称为依赖注入。您的MovingPlatform类依赖于地图,并且您通过构造函数注入该依赖项。

编辑:

对于碰撞,您可以向Tile和MovingPlatform类添加Bounds属性。这使得更容易获得它们的当前矩形边界。也是MovingPlatform中的IntersectsTile方法,如果平台与指定的tile相交,它将返回true。

class Tile
{
    Rectangle Bounds
    {
        get
        {
            return new Rectangle((int)Position.X, (int)Position.Y, tileWidth, tileHeight);
        }
    }
}

class MovingPlatform
{
    Rectangle Bounds
    {
        get
        {
            return new Rectangle((int)Position.X, (int)Position.Y, platformWidth, platformHeight);
        }
    }

    //returns true if this platform intersects the specified tile
    bool IntersectsTile(Tile tile)
    {
        return Bounds.Intersects(tile.Bounds);
    }
}

然后在每个帧移动平台的Update方法的MovingPlatfom类中,检查移动后是否存在碰撞。如果发生碰撞,则退出运动并反转平台方向,因此下一帧将以相反的方向移动。

class MovingPlatform
{
    void Update(Tile[] collidableTiles)
    {
        Position += direction;

        //test collision
        bool isCollision = CollisionTest(collidableTiles);
        if (isCollision)
        {
            //undo the movement and change direction
            Position -= direction;
            direction = newDirection;
        }
    }

    //returns true if this platform intersects with any of the specified tiles
    bool CollisionTest(Tile[] tiles)
    {
        foreach (Tile tile in tiles)
            if (IntersectsTile(tile))
                return true;
        return false;
    }
}

要使上述工作正常,您需要将地图上的可碰撞图块列表传递给MovingPlatform更新。调用map类中的每个MovingPlatform,向其传递可碰撞的tile列表。

class Map
{
    List<Tile> _collidableTiles;

    void Update(GameTime gameTime)
    {
        foreach (MovingPlatform platform in MovingPlatforms)
        {
            platform.Update(_collidableTiles);
        }
    }
}

这是一种做法。一个更好的方法是,不是传递可碰撞的瓷砖,而是让MovingPlatform抓住它周围的瓷砖并测试它们。

class MovingPlatform
{
    void Update()
    {
        Position += direction;

        //test collision
        Tile[] tiles = _map.GetNearbyTiles(Position);
        foreach (Tile tile in tiles)
            if (tile.IsSolid)
                if (IntersectsTile(tile))
                {
                    //undo the movement and change direction
                    Position -= direction;
                    direction = newDirection;
                    break;
                }
    }
}

因此,所有切片都具有IsSolid属性,任何设置为true的切片都会导致移动平台与它们发生碰撞。

class Tile
{
    bool IsSolid;
}
相关问题