像神奇宝贝一样移动精灵

时间:2015-04-22 20:39:16

标签: c# xna monogame

我有一个游戏,我希望我的角色在我的场地中逐个移动,就像在神奇宝贝中一样。

使用我所拥有的代码,它正在逐个方向移动,只是它会跳过大约4-5个方格的每个键。然后跳来跳去。

有人可以帮助我让我的代码以类似Pokémon的方式工作吗?

我的代码如下。

public class Map {

    private Map() {
        Position = new Vector2(0, 0);
    }

    public string Data { get; set; }

    public string[][] MapData { get; set; }

    public ContentManager Content { get; set; }

    public SpriteBatch SpriteBatch { get; set; }

    public Vector2 Position { get; set; }

    private Vector2 ArrayPosition;

    private readonly Vector2 Speed = new Vector2(40, 32);

    public static Map Parse(string path) {
        var map = new Map();
        var stream = TitleContainer.OpenStream(Path.Combine("Content", path));
        using (var sr = new StreamReader(stream)) {
            map.Data = sr.ReadToEnd();
        }
        var lines = map.Data.Split(new string[1] { Environment.NewLine }, StringSplitOptions.None);
        var mapHeight = lines.Count();
        map.MapData = new string[mapHeight][];
        for (int i = 0; i < lines.Count(); i++) {
            var elements = lines[i].Split(';');
            map.MapData[i] = elements;
        }
        return map;
    }

    public void DrawMap(SpriteBatch spriteBatch, ContentManager content, GameTime gametime) {
        this.SpriteBatch = spriteBatch;
        this.Content = content;
        for (int y = 0; y < MapData.Count(); y++) {
            var current = MapData[y];
            for (int x = 0; x < current.Count(); x++) {
                switch (current[x]) {
                    case "e":
                        drawEnemy(x, y);
                        break;

                    case "P":
                    case ".":
                        drawTile(x, y);
                        break;

                    case "w":
                        drawWall(x, y);
                        break;
                }
            }
        }
        drawPlayer();
    }

    public void Move(Direction pdirection, GameTime gametime) {
        var direction = Vector2.Zero;
        var x = this.ArrayPosition.X;
        var y = this.ArrayPosition.Y;
        switch (pdirection) {
            case Direction.Up:
                if (y > 0 && y < 16) {
                    direction = new Vector2(0, -1);
                }
                break;

            case Direction.Down:
                if (y < 16 && y >= 0) {
                    direction = new Vector2(0, 1);
                }
                break;

            case Direction.Left:
                if (x > 0 && x < 16) {
                    direction = new Vector2(-1, 0);
                }
                break;

            case Direction.Right:
                if (x < 16 && x >= 0) {
                    direction = new Vector2(1, 0);
                }
                break;
        }
        Position += direction * Speed;
    }

    private void drawPlayer() {
        var tile = Position / Speed;
        var x = tile.X;
        var y = tile.Y;
        drawTile((int)x, (int)y);
        var texture = Content.Load<Texture2D>("Sprites/player");
        this.SpriteBatch.Draw(texture, Position, Color.White);
    }

    private void drawEnemy(int x, int y) {
        drawTile(x, y);
        drawTexture(Content.Load<Texture2D>("Sprites/enemy"), x, y);
    }

    private void drawTile(int x, int y) {
        drawTexture(Content.Load<Texture2D>("Tiles/grass"), x, y);
    }

    private void drawWall(int x, int y) {
        drawTexture(Content.Load<Texture2D>("Tiles/wall"), x, y);
    }

    private void drawTexture(Texture2D texture, int x, int y) {
        var rectangle = new Rectangle(x * 40, y * 32, 40, 32);
        this.SpriteBatch.Draw(texture, rectangle, Color.White);
    }
}

1 个答案:

答案 0 :(得分:1)

在我看来,除了可能的累积移动增量误差之外,您还在使用混合的坐标系来表示地图上的内容。考虑使用一个协调系统。我不确定你的地图有多大,所以我们假设它是10x10。因此瓷砖;敌人;并且玩家的坐标应该在{0 ... 9} x {0 ... 9}之内。

e.g。在DrawMap()我看到你的瓷砖使用的坐标系统为string[][] MapData的尺寸。你将坐标缩放到下面的drawTexture(),我认为这是一个好主意:

private void drawTexture(Texture2D texture, int x, int y) {
    var rectangle = new Rectangle(x * 40, y * 32, 40, 32);
    this.SpriteBatch.Draw(texture, rectangle, Color.White);
}

提示:尽量避免在代码中使用幻数。考虑将40和32定义为常量,或者在LoadContent()期间更好地确定运行时的切片大小。

但是,根据Move()移动玩家的方法direction按以下定义的Speed缩放为:

private readonly Vector2 Speed = new Vector2(40, 32);

......我认为这不是一个好主意,因为你正在以玩家的速度缩放瓷砖的大小,这导致玩家的坐标完全处于完全状态不同的坐标系统比敌人的墙壁和其他地图数据。因为它是缩放的,所以每当你想要与地图互动时,你需要一直按照平铺大小来规范玩家的坐标。

稍后当您绘制播放器时,您会看到这条不寻常的线:

private void drawPlayer() {
    var tile = Position / Speed;

如果p是位置,v是速度; t是时间;然后p = vt跟随t = p / v,因此只需阅读上面的这一行就有点奇怪了。但我知道你要做什么 - 根据瓷砖尺寸确定瓷砖的坐标。

但是,如果您只是将玩家的位置标准化为始终使用范围{0 ... MapData维度}而不缩放(40,32),则可以使事情更简单。

更改

Move()方法中更改此行:

    Position += direction * Speed;

...为:

    Position += direction;

然后从:

更改drawPlayer()
private void drawPlayer() {
    var tile = Position / Speed;
    var x = tile.X;
    var y = tile.Y;
    drawTile((int)x, (int)y);
    var texture = Content.Load<Texture2D>("Sprites/player");
    this.SpriteBatch.Draw(texture, Position, Color.White);
}

...为:

private void drawPlayer() {
    drawTile((int)Position.x, (int)Position.y);
    var texture = Content.Load<Texture2D>("Sprites/player");

    var p = Position * new Vector2 (40,32);
    this.SpriteBatch.Draw(texture, p, Color.White);
}

表现提示

  • Content.Load<>的所有Drawxxx(...)移至LoadContent(...)。通常,您希望在游戏循环期间最小化资源(特别是相同资源)的负载,除非您的游戏是流式传输(在这种情况下您不是这样)。