zoukankan      html  css  js  c++  java
  • XNA之RPG游戏开发教程之四

    继续上一节,今天主要是要完成游戏中地图的绘制;这里将会用到tiling方法,通过拼图的方式绘制整幅地图。任务如下:搭建有关Tile engine的整体架构

    第一步就是把我们游戏中要用到的Tile下载下来,并添加到EyesOfTheDragonContent中去,下载地址: http://xnagpa.net/xna4/downloads/tilesets.zip

    我们这里使用的Tile引擎是最简单的一种,是分层拼图引擎,很好理解,将地图上的精灵分层绘制,不同层次有不同的精灵元素。在XRpgLibrary下添加一个新的文件夹TileEngine,添加Engine类如下

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework;
    namespace XRpgLibrary.TileEngine
    {
    public class Engine
     {
     #region Field Region
    static int tileWidth;//屏幕宽度方向上tile的个数
    static int tileHeight;//屏幕高度方向上tile的个数 #endregion #region Property Region//这两个属性的对外接口 public static int TileWidth { get { return tileWidth; } } public static int TileHeight { get { return tileHeight; } } #endregion #region Constructors public Engine(int tileWidth, int tileHeight) { Engine.tileWidth = tileWidth; Engine.tileHeight = tileHeight; } #endregion #region Methods//获取一个向量在tile矩阵中的位置 public static Point VectorToCell(Vector2 position) { return new Point((int)position.X / tileWidth, (int)position.Y / tileHeight); } #endregion } }

    地图上的tile当然不是一个,我们要构建一个tileset类来对一个tile集合进行管理

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    namespace XRpgLibrary.TileEngine
    {
    public class Tileset
     {
     #region Fields and PropertiesTexture2D image;
    int tileWidthInPixels;//图片中一个tile的宽度(以像素作为计量)
    int tileHeightInPixels;
    int tilesWide;//图片宽度方向的tile个数
    int tilesHigh;
    Rectangle[] sourceRectangles;//图片中每个tile对应矩形的集合数组
     #endregion
     #region Property Region//对外接口
    public Texture2D Texture
     {
    get { return image; }
    private set { image = value; }
     }
    public int TileWidth
     {
    get { return tileWidthInPixels; }
    private set { tileWidthInPixels = value; }
     }
    public int TileHeight
     {
    get { return tileHeightInPixels; }
    private set { tileHeightInPixels = value; }
     }
    public int TilesWide
     {
    get { return tilesWide; }
    private set { tilesWide = value; }
     }
    public int TilesHigh
     {
    get { return tilesHigh; }
    private set { tilesHigh = value; }
     }
    public Rectangle[] SourceRectangles
     {
    get { return (Rectangle[])sourceRectangles.Clone(); }
     }
     #endregion
     #region Constructor Region
    public Tileset(Texture2D image, int tilesWide, int tilesHigh, int tileWidth, int
    tileHeight)
     {
     Texture = image;
     TileWidth = tileWidth;
     TileHeight = tileHeight;
     TilesWide = tilesWide;
     TilesHigh = tilesHigh;
    int tiles = tilesWide * tilesHigh;
     sourceRectangles = new Rectangle[tiles];
    int tile = 0;
    //初始化图片中tile所对应的矩形区域
    for (int y = 0; y < tilesHigh; y++) for (int x = 0; x < tilesWide; x++) { sourceRectangles[tile] = new Rectangle( x * tileWidth, y * tileHeight, tileWidth, tileHeight); tile++; } } #endregion #region Method Region #endregion } }

    以上代码可以看出,对于tile对象的管理是通过其在tileset中的索引来实现的,为了更好的管理tile,同时也为实现多层的map,构建以tile类来对其信息进行管理

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace XRpgLibrary.TileEngine{
    public class Tile
     {
     #region Field Region
     int tileIndex;//tile在当前集合中的索引
     int tileset;//tile所在集合的索引
     #endregion
     #region Property Region
    public int TileIndex
     {
      get { return tileIndex; }
      private set { tileIndex = value; }
     }
    public int Tileset
     {
      get { return tileset; }
      private set { tileset = value; }
     }
     #endregion
     #region Constructor Region
    public Tile(int tileIndex, int tileset)
     {
      TileIndex = tileIndex;
      Tileset = tileset;
     }
     #endregion
     }
    }

    下面构建一个地图层级类,来管理每一层地图的绘制,代码如下

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace XRpgLibrary.TileEngine
    {
    public class MapLayer
     {
     #region Field Region
     Tile[,] map;//Tile类型的数组,用于存储一层中所有Tile对象
     #endregion
     #region Property Region
    public int Width
     {
    get { return map.GetLength(1); }//获得地图的宽
     }
    public int Height
     {
    get { return map.GetLength(0); }//获得地图的高
     }
     #endregion
     #region Constructor Region//用tile数组对象来初始化地图层对象
    public MapLayer(Tile[,] map)
     {
    this.map = (Tile[,])map.Clone();
     }
    //用宽,高来初始化一层地图对象
    public MapLayer(int width, int height) { map = new Tile[height, width]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { map[y, x] = new Tile(0, 0);//地图中的每个对象都初始化为第0个tileset集合中的第0个tile } } } #endregion #region Method Region//对外接口 public Tile GetTile(int x, int y) { return map[y, x]; } public void SetTile(int x, int y, Tile tile) { map[y, x] = tile; } public void SetTile(int x, int y, int tileIndex, int tileset) { map[y, x] = new Tile(tileIndex, tileset); } #endregion } }

    紧接着就是构造TileMap类,这也是整个地图机制中的核心类,绘制地图的主要逻辑实现都在该类中,先看代码吧

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    namespace XRpgLibrary.TileEngine
    {
    public class TileMap
     {
     #region Field Region
    List<Tileset> tilesets;//tile集合队列
    List<MapLayer> mapLayers;//地图层级队列
     #endregion
     #region Property Region
     #endregion
     #region Constructor Region//构造函数
    public TileMap(List<Tileset> tilesets, List<MapLayer> layers)
     {
    this.tilesets = tilesets;
    this.mapLayers = layers;
     }public TileMap(Tileset tileset, MapLayer layer)
     {
     tilesets = new List<Tileset>();
     tilesets.Add(tileset);
     mapLayers = new List<MapLayer>();
     mapLayers.Add(layer);
     }
     #endregion
     #region Method Region
    //地图绘制 public void Draw(SpriteBatch spriteBatch) {
    //根据Engine对象初始化一个绘制矩形区域 Rectangle destination
    = new Rectangle(0, 0, Engine.TileWidth, Engine.TileHeight); Tile tile;
    //最外层的是地图层级的遍历
    foreach (MapLayer layer in mapLayers) {
    //对该层地图上的每个tile进行遍历,绘制
    for (int y = 0; y < layer.Height; y++) { destination.Y = y * Engine.TileHeight; for (int x = 0; x < layer.Width; x++) { tile = layer.GetTile(x, y); destination.X = x * Engine.TileWidth; spriteBatch.Draw( tilesets[tile.Tileset].Texture, destination, tilesets[tile.Tileset].SourceRectangles[tile.TileIndex], Color.White); } } } } #endregion } }

    最后一步就是要将地图的绘制到GamePlayScreen页面上,该页面代码更改如下

    #region Field Region
    Engine engine = new Engine(32, 32);
    Tileset tileset;
    TileMap map;
    #endregion

    先添加几个类级变量,接下来要在LoadContent方法中加载绘制地图要用的相关对象

    protected override void LoadContent()
    { 
     Texture2D tilesetTexture = Game.Content.Load<Texture2D>(@"Tilesets\tileset1");
     tileset = new Tileset(tilesetTexture, 8, 8, 32, 32);
     MapLayer layer = new MapLayer(40, 40);
    for (int y = 0; y < layer.Height; y++)
     {
    for (int x = 0; x < layer.Width; x++)
     {
     Tile tile = new Tile(0, 0);
     layer.SetTile(x, y, tile);
     }
     }
     map = new TileMap(tileset, layer);
    base.LoadContent();
    }

    最后是绘制地图

    public override void Draw(GameTime gameTime)
    {
     GameRef.SpriteBatch.Begin(
    SpriteSortMode.Immediate,
    BlendState.AlphaBlend,
    SamplerState.PointClamp,
    null,
    null,
    null,
    Matrix.Identity);
     map.Draw(GameRef.SpriteBatch);
    base.Draw(gameTime);
     GameRef.SpriteBatch.End();
    }

  • 相关阅读:
    20200209 ZooKeeper 3. Zookeeper内部原理
    20200209 ZooKeeper 2. Zookeeper本地模式安装
    20200209 Zookeeper 1. Zookeeper入门
    20200206 尚硅谷Docker【归档】
    20200206 Docker 8. 本地镜像发布到阿里云
    20200206 Docker 7. Docker常用安装
    20200206 Docker 6. DockerFile解析
    20200206 Docker 5. Docker容器数据卷
    20200206 Docker 4. Docker 镜像
    Combining STDP and Reward-Modulated STDP in Deep Convolutional Spiking Neural Networks for Digit Recognition
  • 原文地址:https://www.cnblogs.com/zcftech/p/2999359.html
Copyright © 2011-2022 走看看