平铺地图碰撞检测

时间:2012-03-28 22:32:28

标签: c# map xna collision-detection

我一直在查看其他问题,但似乎无法解决这个问题。我在自定义tilemap加载器中使用XNA。这是代码。 http://pastebin.com/cuatQHTb

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Pressure
{

    public class Game1 : Microsoft.Xna.Framework.Game
    {


        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D player;
        Vector2 pos = Vector2.Zero;
        Vector2 playersp = new Vector2(50.0f, 50.0f);
        Texture2D road1;
        Texture2D road2;
        Texture2D brickwall;
        Texture2D floor1;
        Texture2D floor2;
        Texture2D floor3;
        Texture2D grass;
        Texture2D sidewalk1;
        Texture2D wood;
        Texture2D road3;
        private Vector2 origin;
        KeyboardState currentState;
        Camera camera = new Camera();

        Vector2 motion;

        List<Texture2D> tiles = new List<Texture2D>();

        static int tileWidth = 64;
        static int tileHeight = 64;

        int tileMapWidth;
        int tileMapHeight;

        static int screenWidth;
        static int screenHeight;

        static int mapWidthInPixels;
        static int mapHeightInPixels;
        int[,] map = {
              {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 6, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 6, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 8, 1, 1, 1, 2, 2, 1, 8, 7, 5, 6, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 8, 1, 1, 1, 2, 2, 1, 8, 7, 5, 5, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 8, 1, 1, 1, 1, 1, 1, 8, 7, 5, 5, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 8, 1, 3, 3, 3, 1, 1, 8, 7, 5, 6, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 8, 8, 1, 1, 8, 8, 8, 8, 7, 5, 6, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,},
              {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,},
              {9, 9, 9, 5, 5, 9, 9, 9, 5, 5, 9, 9, 9, 5, 5, 5, 5, 5, 9, 9, 9, 5, 5, 9, 9, 9, 5, 5, 9,},
              {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,},
              {7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,},
              {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
              {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
                     };
        public static int ScreenWidth
        {
            get { return screenWidth; }
        }

        public static int ScreenHeight
        {
            get { return screenHeight; }
        }

        public static int MapWidthInPixels
        {
            get { return mapWidthInPixels; }
        }

        public static int MapHeightInPixels
        {
            get { return mapHeightInPixels; }
        }
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }


        protected override void Initialize()
        {

            base.Initialize();
        }

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

            player = Content.Load<Texture2D>("haz");
            origin.X = player.Width /2;
            origin.Y = player.Height /2;
            grass = Content.Load<Texture2D>("grass");
            floor1 = Content.Load<Texture2D>("floor1");
            floor2 = Content.Load<Texture2D>("floor2");
            floor3 = Content.Load<Texture2D>("floor3");
            wood = Content.Load<Texture2D>("wood");
            road1 = Content.Load<Texture2D>("road1");
            road2 = Content.Load<Texture2D>("road2");
            sidewalk1 = Content.Load<Texture2D>("sidewalk1");
            brickwall = Content.Load<Texture2D>("brickwall");
            road3 = Content.Load<Texture2D>("road3");
            tiles.Add(grass); //0
            tiles.Add(floor1);//1
            tiles.Add(floor2);//2
            tiles.Add(floor3);//3
            tiles.Add(wood);//4
            tiles.Add(road1);//5
            tiles.Add(road2);//6
            tiles.Add(sidewalk1);//7
            tiles.Add(brickwall);//8
            tiles.Add(road3);//9

            tileMapWidth = map.GetLength(1);
            tileMapHeight = map.GetLength(0);

            mapWidthInPixels = tileMapWidth * tileWidth;
            mapHeightInPixels = tileMapHeight * tileHeight;

            screenWidth = GraphicsDevice.Viewport.Width;
            screenHeight = GraphicsDevice.Viewport.Height;
           }


        protected override void UnloadContent()
        {
             }
        private float RotationAngle;
        private float oldx;
        private float oldy;

        protected override void Update(GameTime gameTime)
        {
            oldx = playersp.X;
            oldy = playersp.Y;
    currentState = Keyboard.GetState();
   pos = playersp;

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            IsMouseVisible = true;


            MouseState Mouses = Mouse.GetState();
            Vector2 mouseLook = new Vector2(Mouses.X, Mouses.Y);

            motion = Vector2.Zero;
            Vector2 direction = (playersp ) - mouseLook; 
            float angle = (float)(Math.Atan2(direction.Y, direction.X));

            RotationAngle = angle ; 
            if (currentState.IsKeyDown(Keys.W))
            {
                if (playersp.Y > screenHeight  /4)
                {
                    playersp.Y = playersp.Y - 1;

                }
                else
                {
                    ScrollUp();

                }
            }
            if (currentState.IsKeyDown(Keys.A))
            {
                if (playersp.X > screenWidth / 4)
                {

                        playersp.X = playersp.X - 1;

                }
                else
                {
                    ScrollLeft();


                }
            }
            if (currentState.IsKeyDown(Keys.S)) 
            {
                if (playersp.Y > screenHeight / 1.5f)
                {
                    ScrollDown();
                }else{
                    playersp.Y = playersp.Y + 1; 
                }

            }
            if (currentState.IsKeyDown( Keys.D))
            {

                if (playersp.X > screenWidth / 1.5f)
                {

                    ScrollRight();
                }
                else
                {
                    playersp.X = playersp.X + 1;

                }

            }
            if (motion != Vector2.Zero)
            {
                motion.Normalize();

                camera.Position += motion * camera.Speed;
            }

            base.Update(gameTime);
        }

        private void ScrollUp()
        {
            motion.Y = -0.5f;
        }

        private void ScrollRight()
        {
            motion.X = 0.5f;
        }

        private void ScrollDown()
        {
            motion.Y = 0.5f;
        }

        private void ScrollLeft()
        {
            motion.X = -0.5f;
        }

        private Point VectorToCell(Vector2 vector)
        {
            return new Point(
                        (int)(vector.X / tileWidth),
                        (int)(vector.Y / tileHeight));
        }

        private Vector2 ViewPortVector()
        {
            return new Vector2(
                    screenWidth + tileWidth,
                    screenHeight + tileHeight);
        }


        protected override void Draw(GameTime gameTime)
        {

            GraphicsDevice.Clear(Color.CornflowerBlue);
            DrawMap();




            base.Draw(gameTime);

        }

        private void DrawMap()
        {
            Point cameraPoint = VectorToCell(camera.Position);
            Point viewPoint = VectorToCell(camera.Position +
                                ViewPortVector());

            Point min = new Point();
            Point max = new Point();

            min.X = cameraPoint.X;
            min.Y = cameraPoint.Y;
            max.X = (int)Math.Min(viewPoint.X, map.GetLength(1));
            max.Y = (int)Math.Min(viewPoint.Y, map.GetLength(0));

            Rectangle tileRectangle = new Rectangle(
                    0,
                    0,
                    tileWidth,
                    tileHeight);

            spriteBatch.Begin();

            for (int y = min.Y; y < max.Y; y++)
            {
                for (int x = min.X; x < max.X; x++)
                {
                    tileRectangle.X = x * tileWidth - (int)camera.Position.X;
                    tileRectangle.Y = y * tileHeight - (int)camera.Position.Y;

                    spriteBatch.Draw(tiles[map[y, x]],
                        tileRectangle,
                        Color.White);
                    spriteBatch.Draw(player, pos, null, Color.White, RotationAngle,
      origin, 1.0f, SpriteEffects.None, 0f);
                }
            }

            spriteBatch.End();
        }

    }
}

如何检测瓷砖位置并确保播放器不会进入该瓷砖?谢谢!

1 个答案:

答案 0 :(得分:1)

你可以这样做:

private static float scalingFactor = 10;
private static float mapSizeX = 19;
private static float mapSizeY = 29;
Update中的

if (playersp.Y > screenHeight  /4) {
  int mapX = (int) (playersp.X / scalingFactor);
  int mapY = (int) (playersp.Y / scalingFactor) - 1;
  if (isMovable(mapX, mapY)) {
    playersp.Y = playersp.Y - scalingFactor;
  }
} else {
  ScrollUp();
}

和一种新方法:

public bool isMovable(int mapX, int mapY)
{
  if (mapX < 0 || mapX > 19 || mapY < 0 || mapY > 29) {
    return false;
  }

  int tile = map[mapX, mapY];
  if (tile == 4 || tile == 8) {
    return false;
  }

  return true;
}

同样适用于其他方向。

上面的代码调用函数isMovable来决定玩家是否可以根据存储在该位置的地图中的图块类型移动到新位置。如果它是木头或砖墙,那么这个决定是错误的(玩家不能移动到那里),否则就是这样。

缩放系数用于在屏幕位置(在playersp中捕获)和平铺贴图之间进行映射。在这种情况下,每个图块相当于10个屏幕“像素”(如果您愿意,可以将其分为两个单独的比例:一个用于X维度,另一个用于Y)。

注意,您需要确保值mapSizeXmapSizeY正确无误。

最好是为瓷砖类型引入命名常量而不是使用数字 - 这将使您的代码更具可读性(将来和其他人阅读它)。

编辑:更新的代码&amp;解释