在我的 Gemstone Hunter 项目中,我使用了多个 MapSquare,但对它们的使用方式感到困惑。首先,他们在做什么?( static private MapSquare[,] mapCells = new MapSquare[MapWidth, MapHeight];
) 它是在制作mapCells
,然后给它实际的形状,它使用 int 的MapWidth
和MapHeight
?mapCells[x, y] = new MapSquare(skyTile, 0, 0, "", true);
当它只能容纳 x 和 y 更不用说一个字符串和 5 个变量时,它又如何呢?
代码:
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.Storage;
using System.IO;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Tile_Engine
{
public static class TileMap
{
#region Declarations
//TileWidth, and TileHeight are the size that each tile will be when playing and editing the game.
public const int TileWidth = 48;
public const int TileHeight = 48;
//MapWidth and MapHeight create the world size
public const int MapWidth = 160;
public const int MapHeight = 12;
//MapLyaers represent the three back grounds in the MapSquare class.
public const int MapLayers = 3;
//skyTile is the blue tile that will be on the background, or the
private const int skyTile = 2;
//MapSquare organizes the tile sheet into map cells by width and height.
static private MapSquare[,] mapCells =
new MapSquare[MapWidth, MapHeight];
//Tells the the game if its playing or editing the maps.
public static bool EditorMode = true;
public static SpriteFont spriteFont;
static private Texture2D tileSheet;
#endregion
#region Initialization
//The Initialize() method establishes all of the MapCells as MapSquares with empty tiles on each layer.
//On back ground skyTile (2) will be the blue background, 0 will be transparent.
static public void Initialize(Texture2D tileTexture)
{
tileSheet = tileTexture;
for (int x = 0; x < MapWidth; x++)//How long the map is.
{
for (int y = 0; y < MapHeight; y++)//How high is the map.
{
for (int z = 0; z < MapLayers; z++)//In this case z is 3, for background, interactive, and forground.
{
mapCells[x, y] = new MapSquare(skyTile, 0, 0, "", true);
}
}
}
}
#endregion
#region Tile and Tile Sheet Handling
//TilesPerRow calls on a get to do the math to use latter in TileSourceRectangle()
public static int TilesPerRow
{
get { return tileSheet.Width / TileWidth; }
}
public static Rectangle TileSourceRectangle(int tileIndex)
{
return new Rectangle(
(tileIndex % TilesPerRow) * TileWidth,
(tileIndex / TilesPerRow) * TileHeight,
TileWidth,
TileHeight);
}
#endregion
#region Information about Map Cells
static public int GetCellByPixelX(int pixelX)
{
return pixelX / TileWidth;
}
static public int GetCellByPixelY(int pixelY)
{
return pixelY / TileHeight;
}
static public Vector2 GetCellByPixel(Vector2 pixelLocation)
{
return new Vector2(
GetCellByPixelX((int)pixelLocation.X),
GetCellByPixelY((int)pixelLocation.Y));
}
static public Vector2 GetCellCenter(int cellX, int cellY)
{
return new Vector2(
(cellX * TileWidth) + (TileWidth / 2),
(cellY * TileHeight) + (TileHeight / 2));
}
static public Vector2 GetCellCenter(Vector2 cell)
{
return GetCellCenter(
(int)cell.X,
(int)cell.Y);
}
static public Rectangle CellWorldRectangle(int cellX, int cellY)
{
return new Rectangle(
cellX * TileWidth,
cellY * TileHeight,
TileWidth,
TileHeight);
}
static public Rectangle CellWorldRectangle(Vector2 cell)
{
return CellWorldRectangle(
(int)cell.X,
(int)cell.Y);
}
static public Rectangle CellScreenRectangle(int cellX, int cellY)
{
return Camera.WorldToScreen(CellWorldRectangle(cellX, cellY));
}
static public Rectangle CellSreenRectangle(Vector2 cell)
{
return CellScreenRectangle((int)cell.X, (int)cell.Y);
}
static public bool CellIsPassable(int cellX, int cellY)
{
MapSquare square = GetMapSquareAtCell(cellX, cellY);
if (square == null)
return false;
else
return square.Passable;
}
static public bool CellIsPassable(Vector2 cell)
{
return CellIsPassable((int)cell.X, (int)cell.Y);
}
static public bool CellIsPassableByPixel(Vector2 pixelLocation)
{
return CellIsPassable(
GetCellByPixelX((int)pixelLocation.X),
GetCellByPixelY((int)pixelLocation.Y));
}
static public string CellCodeValue(int cellX, int cellY)
{
MapSquare square = GetMapSquareAtCell(cellX, cellY);
if (square == null)
return "";
else
return square.CodeValue;
}
static public string CellCodeValue(Vector2 cell)
{
return CellCodeValue((int)cell.X, (int)cell.Y);
}
#endregion
#region Information about MapSquare objects
static public MapSquare GetMapSquareAtCell(int tileX, int tileY)
{
if ((tileX >= 0) && (tileX < MapWidth) &&
(tileY >= 0) && (tileY < MapHeight))
{
return mapCells[tileX, tileY];
}
else
{
return null;
}
}
static public void SetMapSquareAtCell(
int tileX,
int tileY,
MapSquare tile)
{
if ((tileX >= 0) && (tileX < MapWidth) &&
(tileY >= 0) && (tileY < MapHeight))
{
mapCells[tileX, tileY] = tile;
}
}
//SetTileAtCell()'s prupose is to provide a way to change the tile index of a single layer in a cell without repackaging the cell's entire MapSquare object.
//By passing SetTileAtCell() a cell location, layer number, and tile index, we can change the content of a single layer--exactly what we will need to do when
//building the map editor.
static public void SetTileAtCell(
int tileX,
int tileY,
int layer,
int tileIndex)
{
if ((tileX >= 0) && (tileX < MapWidth) &&
(tileY >= 0) && (tileY < MapHeight))
{
mapCells[tileX, tileY].LayerTiles[layer] = tileIndex;
}
}
static public MapSquare GetMapSquareAtPixel(int pixelX, int pixelY)
{
return GetMapSquareAtCell(
GetCellByPixelX(pixelX),
GetCellByPixelY(pixelY));
}
static public MapSquare GetMapSquareAtPixel(Vector2 pixelLocation)
{
return GetMapSquareAtPixel(
(int)pixelLocation.X,
(int)pixelLocation.Y);
}
#endregion
#region Drawing
static public void Draw(SpriteBatch spriteBatch)
{
int startX = GetCellByPixelX((int)Camera.Position.X);
int endX = GetCellByPixelX((int)Camera.Position.X +
Camera.ViewPortWidth);
int startY = GetCellByPixelY((int)Camera.Position.Y);
int endY = GetCellByPixelY((int)Camera.Position.Y +
Camera.ViewPortHeight);
for (int x = startX; x <= endX; x++)
for (int y = startY; y <= endY; y++)
{
for (int z = 0; z < MapLayers; z++)
{
if ((x >= 0) && (y >= 0) &&
(x < MapWidth) && (y < MapHeight))
{
spriteBatch.Draw(
tileSheet,
CellScreenRectangle(x, y),
TileSourceRectangle(
mapCells[x, y].LayerTiles[z]),
Color.White,
0.0f,
Vector2.Zero,
SpriteEffects.None,
1f - ((float)z * 0.1f));
}
}
if (EditorMode)
{
DrawEditModeItems(spriteBatch, x, y);
}
}
}
public static void DrawEditModeItems(
SpriteBatch spriteBatch,
int x,
int y)
{
if ((x < 0) || (x >= MapWidth) ||
(y < 0) || (y >= MapHeight))
return;
if (!CellIsPassable(x, y))
{
spriteBatch.Draw(
tileSheet,
CellScreenRectangle(x, y),
TileSourceRectangle(1),
new Color(255, 0, 0, 80),
0.0f,
Vector2.Zero,
SpriteEffects.None,
0.0f);
}
if (mapCells[x, y].CodeValue != "")
{
Rectangle screenRect = CellScreenRectangle(x, y);
spriteBatch.DrawString(
spriteFont,
mapCells[x, y].CodeValue,
new Vector2(screenRect.X, screenRect.Y),
Color.White,
0.0f,
Vector2.Zero,
1.0f,
SpriteEffects.None,
0.0f);
}
}
#endregion
#region Loading and Saving Maps
public static void SaveMap(FileStream fileStream)
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fileStream, mapCells);
fileStream.Close();
}
public static void LoadMap(FileStream fileStream)
{
try
{
BinaryFormatter formatter = new BinaryFormatter();
mapCells =
(MapSquare[,])formatter.Deserialize(fileStream);
fileStream.Close();
}
catch
{
ClearMap();
}
}
public static void ClearMap()
{
for (int x = 0; x < MapWidth; x++)
for (int y = 0; y < MapHeight; y++)
for (int z = 0; z < MapLayers; z++)
{
mapCells[x, y] = new MapSquare(2, 0, 0, "", true);
}
}
#endregion
}
}