我正在使用瓷砖地图,如果移动平台击中瓷砖,它应该朝另一个方向发展。我正在使用tilemap和platform的列表,这有助于保持整洁。
下面的图片显示了平台,它始终处于运动状态,当它与其中一个黑色圆圈发生碰撞时,它应该改变方向并以与它相反的方式前进。
不幸的是我遇到了一个问题,我需要找到正确的平台,以便它会朝另一个方向发展。我在主类中创建了列表,并且不知道如何调用除main之外的另一个类中的列表。
问题:
如何调用一个包含多个对象的列表,这些列表位于不同的位置,位于不同的位置,并在主类中创建,以便我可以知道平台是否与磁贴碰撞?
简单地说,如何让平台与瓷砖碰撞?
以下是瓷砖地图必须经过使用和调用的过程:
要使tile图使用两个类,Block类和Game1类(主类)。
在Block类中,Texture,Position和BlockState(决定它将做什么)
public Block(Texture2D Texture, Vector2 Position, int BlockState)
{
this.Texture = Texture;
this.Position = Position;
this.BlockState = BlockState;
}
然后Block类将使用一个使用Player类的方法。
public Player BlockCollision(Player player)
{
Rectangle top = new Rectangle((int)Position.X + 5, (int)Position.Y - 10, Texture.Width - 10, 10);
Rectangle bottom = new Rectangle((int)Position.X + 5, (int)Position.Y + Texture.Height, Texture.Width - 10, 10);
Rectangle left = new Rectangle((int)Position.X - 10, (int)Position.Y + 5, 10, Texture.Height - 10);
Rectangle right = new Rectangle((int)Position.X + Texture.Width, (int)Position.Y + 5, 10, Texture.Height - 10);
if (BlockState == 1 || (BlockState == 2 && !player.goingUp))
{
if (top.Intersects(new Rectangle((int)player.Position.X, (int)player.Position.Y, player.Texture.Width, player.Texture.Height)))
{
if (player.Position.Y + player.Texture.Height > Position.Y && player.Position.Y + player.Texture.Height < Position.Y + Texture.Height / 2)
{
player.Position.Y = player.ground = Position.Y - player.Texture.Height;
player.Velocity.Y = 0;
player.isJumping = false;
player.Time = 0;
player.botCollision = true;
}
}
}
return player;
}
然后是Draw方法。
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height), Color.White);
}
然后我们转到主要类Game1。
我为块和平台创建了列表。
List<Block> Blocks;
List<MovingPlatform> Platforms;
使用char系统我创建地图。
List<char[,]> Levels = new List<char[,]>();
public int tileWidth, tileHeight;
然后在Initialize方法中,我调用Lists并创建地图。
protected override void Initialize()
{
Blocks = new List<Block>();
Platforms = new List<MovingPlatform>();
char[,] Level1 = {{'.','.','#'},
{'.','.','#'},
{'.','.','#'}};
Levels.Add(Level1);
base.Initialize();
}
然后调用void LoadLevel。
void LoadLevel(int level)
{
Blocks.Clear();
Platforms.Clear();
player.Position = Vector2.Zero;
tileWidth = Levels[level].GetLength(1);
tileHeight = Levels[level].GetLength(0);
Texture2D blockSpriteA = Content.Load<Texture2D>("blockA2");
for (int x = 0; x < tileWidth; x++)
{
for (int y = 0; y < tileHeight; y++)
{
//Background
Blocks.Add(new Block(background, new Vector2(x * 50, y * 50), 0));
//Impassable Blocks
if (Levels[level][y, x] == '#')
{
Blocks.Add(new Block(blockSpriteA, new Vector2(x * 50, y * 50), 1));
}
//Vertical Moving Platform
if (Levels[level][y, x] == '=')
{
Platforms.Add(new MovingPlatform(platform, new Vector2(x * 50, y * 50), 3.0f, true));
}
然后在更新中我打电话给列表。
foreach (Block b in Blocks)
{
player = b.BlockCollision(player);
}
foreach (MovingPlatform m in Platforms)
{
player = m.BlockCollision(player);
m.Update(gameTime);
}
最后,Draw方法会调用它们。
foreach (Block b in Blocks)
{
b.Draw(spriteBatch);
}
foreach (MovingPlatform m in Platforms)
{
m.Draw(spriteBatch);
}
答案 0 :(得分:1)
我想我理解你的问题,我不确定,但无论如何我都会冒险回答。
我认为你需要做的是将东西移出主游戏类。你有一个地图的概念和一堆属于地图(平台,块)的东西,所以将它封装在自己的类中是一个好主意,例如:
class Map
{
public List<Block> Blocks;
public List<MovingPlatform> Platforms;
void LoadLevel(int level)
{
///
}
}
现在它使代码更清晰,但你现在还有一个可以传递的Map对象。
因此,例如,为了使MovingPlatform能够访问地图上的所有内容,您只需将对地图的引用作为参数传递给MovingPlatform构造函数,该构造函数将其保存到私有字段。例如:
class MovingPlatform
{
Map _map;
public MovingPlatform(Map map, Vector2 position, ...)
{
_map = map;
}
public void Update(GameTime gameTime)
{
//move platform
//detect collision
//have access to all the blocks and other platforms on map
//_map.Blocks;
//_map.Platforms;
}
}
因此,在地图类LoadLevel()方法中,您将传入&#39;这个&#39;作为MovingPlatform构造函数的第一个参数:
class Map
{
void LoadLevel(int level)
{
//Vertical Moving Platform
if (Levels[level][y, x] == '=')
{
Platforms.Add(new MovingPlatform(this, ...));
}
}
}
您可以将其他地图特定内容(甚至是对播放器的引用?)添加到Map类中,MovingPlatforms将自动访问它们。
这称为依赖注入。您的MovingPlatform类依赖于地图,并且您通过构造函数注入该依赖项。
编辑:
对于碰撞,您可以向Tile和MovingPlatform类添加Bounds属性。这使得更容易获得它们的当前矩形边界。也是MovingPlatform中的IntersectsTile方法,如果平台与指定的tile相交,它将返回true。
class Tile
{
Rectangle Bounds
{
get
{
return new Rectangle((int)Position.X, (int)Position.Y, tileWidth, tileHeight);
}
}
}
class MovingPlatform
{
Rectangle Bounds
{
get
{
return new Rectangle((int)Position.X, (int)Position.Y, platformWidth, platformHeight);
}
}
//returns true if this platform intersects the specified tile
bool IntersectsTile(Tile tile)
{
return Bounds.Intersects(tile.Bounds);
}
}
然后在每个帧移动平台的Update方法的MovingPlatfom类中,检查移动后是否存在碰撞。如果发生碰撞,则退出运动并反转平台方向,因此下一帧将以相反的方向移动。
class MovingPlatform
{
void Update(Tile[] collidableTiles)
{
Position += direction;
//test collision
bool isCollision = CollisionTest(collidableTiles);
if (isCollision)
{
//undo the movement and change direction
Position -= direction;
direction = newDirection;
}
}
//returns true if this platform intersects with any of the specified tiles
bool CollisionTest(Tile[] tiles)
{
foreach (Tile tile in tiles)
if (IntersectsTile(tile))
return true;
return false;
}
}
要使上述工作正常,您需要将地图上的可碰撞图块列表传递给MovingPlatform更新。调用map类中的每个MovingPlatform,向其传递可碰撞的tile列表。
class Map
{
List<Tile> _collidableTiles;
void Update(GameTime gameTime)
{
foreach (MovingPlatform platform in MovingPlatforms)
{
platform.Update(_collidableTiles);
}
}
}
这是一种做法。一个更好的方法是,不是传递可碰撞的瓷砖,而是让MovingPlatform抓住它周围的瓷砖并测试它们。
class MovingPlatform
{
void Update()
{
Position += direction;
//test collision
Tile[] tiles = _map.GetNearbyTiles(Position);
foreach (Tile tile in tiles)
if (tile.IsSolid)
if (IntersectsTile(tile))
{
//undo the movement and change direction
Position -= direction;
direction = newDirection;
break;
}
}
}
因此,所有切片都具有IsSolid属性,任何设置为true的切片都会导致移动平台与它们发生碰撞。
class Tile
{
bool IsSolid;
}