【问题标题】:MonoGame + TiledSharp CollisionMonoGame + TiledSharp 碰撞
【发布时间】:2016-09-14 17:02:42
【问题描述】:

我正在使用 Tiled (http://www.mapeditor.org) 来生成我的地图,并使用 TiledSharp (https://github.com/marshallward/TiledSharp) 来加载和绘制我的地图。

到目前为止一切顺利。地图绘制正确(在正确的图层中)并且英雄移动正确。

我没有得到什么。如何检查玩家和物体之间的碰撞?

在我的 Update() 中我有类似的东西

if (ks.IsKeyDown(Keys.W))
{
    playerMovement += new Vector2(0, -2);
    curAnimation = "Walk_North";
}

...

if (playerMovement.Length() != 0)
    player.MoveBy(playerMovement);

检查地图的 .tmx 文件,我的组中有我可以碰撞的对象:

 <objectgroup name="Collision">
  <properties>
   <property name="collision" type="bool" value="true"/>
  </properties>
  <object id="1" x="1089" y="1118" width="62" height="65"/>
  <object id="2" x="801" y="1026" width="61" height="60"/>
 </objectgroup>

我现在正在寻找的是类似的东西

If(tileAt(player.Position + playerMovement).Properties.Collision)
    playerMovement = Vector2.Zero();   

我想,我需要的一切都在那里,我只是缺少一个简单的步骤来比较玩家的位置与目标位置及其属性:(

任何建议或示例将不胜感激。 (也许只需要自己用简单的方法计算一下就可以了……)

【问题讨论】:

    标签: collision-detection monogame tiled


    【解决方案1】:

    想通了,其实很简单:

    首先,在我的班级管理我的地图中,我用我的碰撞对象设置了一个列表。

    foreach(var o in curMap.ObjectGroups["Collision"].Objects)
        collisionObjects.Add(new Rectangle((int)o.X, (int)o.Y, (int)o.Width, (int)o.Height));
    

    在我的 UpdateGame() 方法中,我从我的地图类中调用一个简单的辅助方法来检查交叉点:

    public bool IsCollisionTile(Rectangle player)
    {
        foreach (Rectangle rect in collisionObjects)
            if (rect.Intersects(player))
               return true;
    
        return false;
    }
    

    完成。

    写这篇文章比实际实现要花更多的精力^^

    【讨论】:

      【解决方案2】:

      我已经测试了你的代码,但是当我启动我的游戏时他不起作用,在 foreach 中显示一个异常,他说在字典中找不到密钥

      它是我的类 MapLoader

      using Microsoft.Xna.Framework;
      using Microsoft.Xna.Framework.Graphics;
      using Microsoft.Xna.Framework.Content;
      
      using System;
      using System.Collections.Generic;
      
      using TiledSharp;
      
      namespace TestMapLoader
      {
          public class MapLoader
          {
              private TmxMap _map;
              private Texture2D _tileset;
              private int _tileWidth;
              private int _tileHeight;
              private int _mapWidth;
              private int _mapHeight;
              private int _tilesetTilesWide;
              private int _tilesetTilesHigh;
              private List<Rectangle> _collisionObject;
      
              public MapLoader()
              {
              }
      
              public void LoadContent(ContentManager content, string path)
              {
                  _collisionObject = new List<Rectangle>();
      
                  _map = new TmxMap(path);
                  _tileset = content.Load<Texture2D>(_map.Tilesets[0].Name.ToString());
      
                  _tileWidth = _map.Tilesets[0].TileWidth;
                  _tileHeight = _map.Tilesets[0].TileHeight;
      
                  _tilesetTilesWide = _tileset.Width / _tileWidth;
                  _tilesetTilesHigh = _tileset.Height / _tileHeight;
      
                  _mapWidth = _map.Width;
                  _mapHeight = _map.Height;
              }
      
              public void Update()
              {
              }
      
              public void Draw(SpriteBatch spriteBatch ,int nbLayer)
              {
                  spriteBatch.Begin();
      
                  for (int nLayer = 0; nLayer < nbLayer; nLayer++)
                  {
                      for (var i = 0; i < _map.Layers[nLayer].Tiles.Count; i++)
                      {
                          int gid = _map.Layers[nLayer].Tiles[i].Gid;
      
                          if (gid != 0)
                          {
                              int tileFrame = gid - 1;
                              int column = tileFrame % _tilesetTilesWide;
                              int row = (int)Math.Floor((double)tileFrame / (double)_tilesetTilesWide);
      
                              int mapRow = (int)(i / _mapWidth);
                              int mapColumn = i % _mapWidth;
      
                              float x = (i % _map.Width) * _map.TileWidth;
                              float y = (float)Math.Floor(i / (double)_map.Width) * _map.TileHeight;
      
                              Rectangle tilesetRec = new Rectangle(_tileWidth * column, _tileHeight * row, _tileWidth, _tileHeight);
      
                              spriteBatch.Draw(_tileset, new Rectangle((int)x, (int)y, _tileWidth, _tileHeight), tilesetRec, Color.White);
                          }
                      }
                  }
      
                  spriteBatch.End();
                  foreach(var o in _map.ObjectGroups["Collision"].Objects)
                  {
                      this._collisionObject.Add(new Rectangle((int)o.X, (int)o.Y, (int)o.Width, (int)o.Height));
                  }
              }
      
              public bool IsCollisionTile(Rectangle player)
              {
                  foreach(Rectangle rect in this._collisionObject)
                  {
                      if (rect.Intersects(player))
                      {
                          return true;
                      }
                  }
                  return false;
              }
      
              public TmxMap getMap()
              {
                  return _map;
              }
          }
      }
      

      我在我的 Game1 类中调用所有函数

      【讨论】:

      • 首先,您不应该在 Draw() 中添加 foreach。在这种情况下,您每秒添加所有碰撞对象 60 次(@60FPS),这非常疯狂;)我在 TileMap 构造函数中添加了 foreach,因为您只需要为每个地图填充一次碰撞对象(假设您一次加载地图) 第二:检查您的 .tmx 文件中是否存在以下 组名区分大小写!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多