MonoGame + TiledSharp 碰撞
MonoGame + TiledSharp Collision
我正在使用 Tiled (http://www.mapeditor.org) to generate my maps and 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();
我想,我需要的一切都在那里,我只是缺少一个简单的步骤来比较玩家的位置与目标位置及其 属性 :(
如有任何建议或示例,我们将不胜感激。
(可能需要自己用简单的方法计算一下...)
想通了,其实很简单:
首先,在我的 class 管理我的地图时,我用我的碰撞对象设置了一个列表。
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() 方法中,我从我的地图中调用了一个简单的辅助方法-class 检查交叉点:
public bool IsCollisionTile(Rectangle player)
{
foreach (Rectangle rect in collisionObjects)
if (rect.Intersects(player))
return true;
return false;
}
完成。
写这篇文章比实际实施更费力^^
我已经测试了你的代码,但是当我启动我的游戏时他不工作,在 foreach 中显示一个异常他说在字典中找不到密钥
这是我的class 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 中的所有函数 class
我正在使用 Tiled (http://www.mapeditor.org) to generate my maps and 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();
我想,我需要的一切都在那里,我只是缺少一个简单的步骤来比较玩家的位置与目标位置及其 属性 :(
如有任何建议或示例,我们将不胜感激。 (可能需要自己用简单的方法计算一下...)
想通了,其实很简单:
首先,在我的 class 管理我的地图时,我用我的碰撞对象设置了一个列表。
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() 方法中,我从我的地图中调用了一个简单的辅助方法-class 检查交叉点:
public bool IsCollisionTile(Rectangle player)
{
foreach (Rectangle rect in collisionObjects)
if (rect.Intersects(player))
return true;
return false;
}
完成。
写这篇文章比实际实施更费力^^
我已经测试了你的代码,但是当我启动我的游戏时他不工作,在 foreach 中显示一个异常他说在字典中找不到密钥
这是我的class 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 中的所有函数 class