瓦片地图碰撞检测 [英] Tile map Collision Detection

查看:204
本文介绍了瓦片地图碰撞检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找通过其他的问题,但似乎无法算出这个..我使用XNA在自定义tilemap的装载机。这里是代码。
http://pastebin.com/cuatQHTb

I've been looking through the other questions but just can't seem to figure this out.. I'm using XNA in a custom tilemap loader. Here is the code. 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();
        }

    }
}



会怎样我检测瓷砖的位置,并确保玩家不会进入的瓷砖? !谢谢

How would I detect the tiles position and make sure the player doesn't enter that tile? thanks!

推荐答案

您可以做这样的事情:

private static float scalingFactor = 10;
private static float mapSizeX = 19;
private static float mapSizeY = 29;

更新

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;
}



同样,对于其他方向。

Similarly for the other directions.

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

The above code calls the function isMovable to decide whether the player can move to the new location based on the type of tile stored in the map at that position. The decision is false (the player cannot move there) if it is wood or brick wall, otherwise it is true.

比例因子是将屏幕位置之间进行映射(在 playersp )和瓦片地图抓获。在这种情况下,每个瓦相当于10屏幕像素(你可以打破它分为两个独立的尺度,如果你想:一个在X渔政船,其他为Y)。

The scaling factor is to map between the screen position (captured in playersp) and the tile map. In this case each tile is equivalent to 10 screen "pixels" (You can break it into two separate scales if you want to: one for X dimention, the other for Y).

请注意,您需要确保值 mapSizeX mapSizeY 是正确的。

Note, you need to make sure the values mapSizeX and mapSizeY are correct.

这将是最好的,如果你推出一个名为瓷砖的种类,而不是使用数字常量 - 它会让你的代码更易读(你的未来,并为他人阅读的话)。

It would be best if you introduced named constants for the type of tile instead of using the numbers -- it will make your code more readable (for you in the future and for others reading it).

编辑:更新的代码和放大器;解释

updated code & explanation

这篇关于瓦片地图碰撞检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆