#region File Description
//-----------------------------------------------------------------------------
// Map.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
#endregion
namespace RolePlayingGameData
{
///
/// One section of the world, and all of the data in it.
///
public class Map : ContentObject
#if WINDOWS
, ICloneable
#endif
{
#region Description
///
/// The name of this section of the world.
///
private string name;
///
/// The name of this section of the world.
///
public string Name
{
get { return name; }
set { name = value; }
}
#endregion
#region Dimensions
///
/// The dimensions of the map, in tiles.
///
private Point mapDimensions;
///
/// The dimensions of the map, in tiles.
///
public Point MapDimensions
{
get { return mapDimensions; }
set { mapDimensions = value; }
}
///
/// The size of the tiles in this map, in pixels.
///
private Point tileSize;
///
/// The size of the tiles in this map, in pixels.
///
public Point TileSize
{
get { return tileSize; }
set { tileSize = value; }
}
///
/// The number of tiles in a row of the map texture.
///
///
/// Used to determine the source rectangle from the map layer value.
///
private int tilesPerRow;
///
/// The number of tiles in a row of the map texture.
///
///
/// Used to determine the source rectangle from the map layer value.
///
[ContentSerializerIgnore]
public int TilesPerRow
{
get { return tilesPerRow; }
}
#endregion
#region Spawning
///
/// A valid spawn position for this map.
///
private Point spawnMapPosition;
///
/// A valid spawn position for this map.
///
public Point SpawnMapPosition
{
get { return spawnMapPosition; }
set { spawnMapPosition = value; }
}
#endregion
#region Graphics Data
///
/// The content name of the texture that contains the tiles for this map.
///
private string textureName;
///
/// The content name of the texture that contains the tiles for this map.
///
public string TextureName
{
get { return textureName; }
set { textureName = value; }
}
///
/// The texture that contains the tiles for this map.
///
private Texture2D texture;
///
/// The texture that contains the tiles for this map.
///
[ContentSerializerIgnore]
public Texture2D Texture
{
get { return texture; }
}
///
/// The content name of the texture that contains the background for combats
/// that occur while traveling on this map.
///
private string combatTextureName;
///
/// The content name of the texture that contains the background for combats
/// that occur while traveling on this map.
///
public string CombatTextureName
{
get { return combatTextureName; }
set { combatTextureName = value; }
}
///
/// The texture that contains the background for combats
/// that occur while traveling on this map.
///
private Texture2D combatTexture;
///
/// The texture that contains the background for combats
/// that occur while traveling on this map.
///
[ContentSerializerIgnore]
public Texture2D CombatTexture
{
get { return combatTexture; }
}
#endregion
#region Music
///
/// The name of the music cue for this map.
///
private string musicCueName;
///
/// The name of the music cue for this map.
///
public string MusicCueName
{
get { return musicCueName; }
set { musicCueName = value; }
}
///
/// The name of the music cue for combats that occur while traveling on this map.
///
private string combatMusicCueName;
///
/// The name of the music cue for combats that occur while traveling on this map.
///
public string CombatMusicCueName
{
get { return combatMusicCueName; }
set { combatMusicCueName = value; }
}
#endregion
#region Map Layers
#region Base Layer
///
/// Spatial array for the ground tiles for this map.
///
private int[] baseLayer;
///
/// Spatial array for the ground tiles for this map.
///
public int[] BaseLayer
{
get { return baseLayer; }
set { baseLayer = value; }
}
///
/// Retrieves the base layer value for the given map position.
///
public int GetBaseLayerValue(Point mapPosition)
{
// check the parameter
if ((mapPosition.X < 0) || (mapPosition.X >= mapDimensions.X) ||
(mapPosition.Y < 0) || (mapPosition.Y >= mapDimensions.Y))
{
throw new ArgumentOutOfRangeException("mapPosition");
}
return baseLayer[mapPosition.Y * mapDimensions.X + mapPosition.X];
}
///
/// Retrieves the source rectangle for the tile in the given position
/// in the base layer.
///
/// This method allows out-of-bound (blocked) positions.
public Rectangle GetBaseLayerSourceRectangle(Point mapPosition)
{
// check the parameter, but out-of-bounds is nonfatal
if ((mapPosition.X < 0) || (mapPosition.X >= mapDimensions.X) ||
(mapPosition.Y < 0) || (mapPosition.Y >= mapDimensions.Y))
{
return Rectangle.Empty;
}
int baseLayerValue = GetBaseLayerValue(mapPosition);
if (baseLayerValue < 0)
{
return Rectangle.Empty;
}
return new Rectangle(
(baseLayerValue % tilesPerRow) * tileSize.X,
(baseLayerValue / tilesPerRow) * tileSize.Y,
tileSize.X, tileSize.Y);
}
#endregion
#region Fringe Layer
///
/// Spatial array for the fringe tiles for this map.
///
private int[] fringeLayer;
///
/// Spatial array for the fringe tiles for this map.
///
public int[] FringeLayer
{
get { return fringeLayer; }
set { fringeLayer = value; }
}
///
/// Retrieves the fringe layer value for the given map position.
///
public int GetFringeLayerValue(Point mapPosition)
{
// check the parameter
if ((mapPosition.X < 0) || (mapPosition.X >= mapDimensions.X) ||
(mapPosition.Y < 0) || (mapPosition.Y >= mapDimensions.Y))
{
throw new ArgumentOutOfRangeException("mapPosition");
}
return fringeLayer[mapPosition.Y * mapDimensions.X + mapPosition.X];
}
///
/// Retrieves the source rectangle for the tile in the given position
/// in the fringe layer.
///
/// This method allows out-of-bound (blocked) positions.
public Rectangle GetFringeLayerSourceRectangle(Point mapPosition)
{
// check the parameter, but out-of-bounds is nonfatal
if ((mapPosition.X < 0) || (mapPosition.X >= mapDimensions.X) ||
(mapPosition.Y < 0) || (mapPosition.Y >= mapDimensions.Y))
{
return Rectangle.Empty;
}
int fringeLayerValue = GetFringeLayerValue(mapPosition);
if (fringeLayerValue < 0)
{
return Rectangle.Empty;
}
return new Rectangle(
(fringeLayerValue % tilesPerRow) * tileSize.X,
(fringeLayerValue / tilesPerRow) * tileSize.Y,
tileSize.X, tileSize.Y);
}
#endregion
#region Object Layer
///
/// Spatial array for the object images on this map.
///
private int[] objectLayer;
///
/// Spatial array for the object images on this map.
///
public int[] ObjectLayer
{
get { return objectLayer; }
set { objectLayer = value; }
}
///
/// Retrieves the object layer value for the given map position.
///
public int GetObjectLayerValue(Point mapPosition)
{
// check the parameter
if ((mapPosition.X < 0) || (mapPosition.X >= mapDimensions.X) ||
(mapPosition.Y < 0) || (mapPosition.Y >= mapDimensions.Y))
{
throw new ArgumentOutOfRangeException("mapPosition");
}
return objectLayer[mapPosition.Y * mapDimensions.X + mapPosition.X];
}
///
/// Retrieves the source rectangle for the tile in the given position
/// in the object layer.
///
/// This method allows out-of-bound (blocked) positions.
public Rectangle GetObjectLayerSourceRectangle(Point mapPosition)
{
// check the parameter, but out-of-bounds is nonfatal
if ((mapPosition.X < 0) || (mapPosition.X >= mapDimensions.X) ||
(mapPosition.Y < 0) || (mapPosition.Y >= mapDimensions.Y))
{
return Rectangle.Empty;
}
int objectLayerValue = GetObjectLayerValue(mapPosition);
if (objectLayerValue < 0)
{
return Rectangle.Empty;
}
return new Rectangle(
(objectLayerValue % tilesPerRow) * tileSize.X,
(objectLayerValue / tilesPerRow) * tileSize.Y,
tileSize.X, tileSize.Y);
}
#endregion
#region Collision Layer
///
/// Spatial array for the collision properties of this map.
///
private int[] collisionLayer;
///
/// Spatial array for the collision properties of this map.
///
public int[] CollisionLayer
{
get { return collisionLayer; }
set { collisionLayer = value; }
}
///
/// Retrieves the collision layer value for the given map position.
///
public int GetCollisionLayerValue(Point mapPosition)
{
// check the parameter
if ((mapPosition.X < 0) || (mapPosition.X >= mapDimensions.X) ||
(mapPosition.Y < 0) || (mapPosition.Y >= mapDimensions.Y))
{
throw new ArgumentOutOfRangeException("mapPosition");
}
return collisionLayer[mapPosition.Y * mapDimensions.X + mapPosition.X];
}
///
/// Returns true if the given map position is blocked.
///
/// This method allows out-of-bound (blocked) positions.
public bool IsBlocked(Point mapPosition)
{
// check the parameter, but out-of-bounds is nonfatal
if ((mapPosition.X < 0) || (mapPosition.X >= mapDimensions.X) ||
(mapPosition.Y < 0) || (mapPosition.Y >= mapDimensions.Y))
{
return true;
}
return (GetCollisionLayerValue(mapPosition) != 0);
}
#endregion
#endregion
#region Portals
///
/// Portals to other maps.
///
private List portals = new List();
///
/// Portals to other maps.
///
public List Portals
{
get { return portals; }
set { portals = value; }
}
#endregion
#region Map Contents
///
/// The content names and positions of the portals on this map.
///
private List> portalEntries =
new List>();
///
/// The content names and positions of the portals on this map.
///
public List> PortalEntries
{
get { return portalEntries; }
set { portalEntries = value; }
}
///
/// Find a portal on this map based on the given portal name.
///
public MapEntry FindPortal(string name)
{
// check the parameter
if (String.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
return portalEntries.Find(delegate(MapEntry portalEntry)
{
return (portalEntry.ContentName == name);
});
}
///
/// The content names and positions of the treasure chests on this map.
///
private List> chestEntries =
new List>();
///
/// The content names and positions of the treasure chests on this map.
///
public List> ChestEntries
{
get { return chestEntries; }
set { chestEntries = value; }
}
///
/// The content name, positions, and orientations of the
/// fixed combat encounters on this map.
///
private List> fixedCombatEntries =
new List>();
///
/// The content name, positions, and orientations of the
/// fixed combat encounters on this map.
///
public List> FixedCombatEntries
{
get { return fixedCombatEntries; }
set { fixedCombatEntries = value; }
}
///
/// The random combat definition for this map.
///
private RandomCombat randomCombat;
///
/// The random combat definition for this map.
///
public RandomCombat RandomCombat
{
get { return randomCombat; }
set { randomCombat = value; }
}
///
/// The content names, positions, and orientations of quest Npcs on this map.
///
private List> questNpcEntries =
new List>();
///
/// The content names, positions, and orientations of quest Npcs on this map.
///
public List> QuestNpcEntries
{
get { return questNpcEntries; }
set { questNpcEntries = value; }
}
///
/// The content names, positions, and orientations of player Npcs on this map.
///
private List> playerNpcEntries =
new List>();
///
/// The content names, positions, and orientations of player Npcs on this map.
///
public List> PlayerNpcEntries
{
get { return playerNpcEntries; }
set { playerNpcEntries = value; }
}
///
/// The content names, positions, and orientations of the inns on this map.
///
private List> innEntries =
new List>();
///
/// The content names, positions, and orientations of the inns on this map.
///
public List> InnEntries
{
get { return innEntries; }
set { innEntries = value; }
}
///
/// The content names, positions, and orientations of the stores on this map.
///
private List> storeEntries =
new List>();
///
/// The content names, positions, and orientations of the stores on this map.
///
public List> StoreEntries
{
get { return storeEntries; }
set { storeEntries = value; }
}
#endregion
#region ICloneable Members
public object Clone()
{
Map map = new Map();
map.AssetName = AssetName;
map.baseLayer = BaseLayer.Clone() as int[];
foreach (MapEntry chestEntry in chestEntries)
{
MapEntry mapEntry = new MapEntry();
mapEntry.Content = chestEntry.Content.Clone() as Chest;
mapEntry.ContentName = chestEntry.ContentName;
mapEntry.Count = chestEntry.Count;
mapEntry.Direction = chestEntry.Direction;
mapEntry.MapPosition = chestEntry.MapPosition;
map.chestEntries.Add(mapEntry);
}
map.chestEntries.AddRange(ChestEntries);
map.collisionLayer = CollisionLayer.Clone() as int[];
map.combatMusicCueName = CombatMusicCueName;
map.combatTexture = CombatTexture;
map.combatTextureName = CombatTextureName;
map.fixedCombatEntries.AddRange(FixedCombatEntries);
map.fringeLayer = FringeLayer.Clone() as int[];
map.innEntries.AddRange(InnEntries);
map.mapDimensions = MapDimensions;
map.musicCueName = MusicCueName;
map.name = Name;
map.objectLayer = ObjectLayer.Clone() as int[];
map.playerNpcEntries.AddRange(PlayerNpcEntries);
map.portals.AddRange(Portals);
map.portalEntries.AddRange(PortalEntries);
map.questNpcEntries.AddRange(QuestNpcEntries);
map.randomCombat = new RandomCombat();
map.randomCombat.CombatProbability = RandomCombat.CombatProbability;
map.randomCombat.Entries.AddRange(RandomCombat.Entries);
map.randomCombat.FleeProbability = RandomCombat.FleeProbability;
map.randomCombat.MonsterCountRange = RandomCombat.MonsterCountRange;
map.spawnMapPosition = SpawnMapPosition;
map.storeEntries.AddRange(StoreEntries);
map.texture = Texture;
map.textureName = TextureName;
map.tileSize = TileSize;
map.tilesPerRow = tilesPerRow;
return map;
}
#endregion
#region Content Type Reader
///
/// Read a Map object from the content pipeline.
///
public class MapReader : ContentTypeReader