2025-04-03 02:30:16 +08:00

194 lines
6.1 KiB
C#

using System;
using System.IO;
using UnityEngine;
namespace MindPowerSdk
{
public partial class MPMap
{
private MPMapFileHeader _mapHeader;
public int Width => _mapHeader.Width;
public int Height => _mapHeader.Height;
public int SectionWidth => _mapHeader.SectionWidth;
public int SectionHeight => _mapHeader.SectionHeight;
// 部分数据的数量(地图分块)
public int SectionCntX;
public int SecitonCntY;
public int SectionCnt;
// 地图块索引偏移
private int[] _offsetIdx;
public MPActiveMapSection[,] ActiveSectionArray;
// private List<MPActiveMapSection> ActiveSections = new();
private BinaryReader _fp;
private MPTile _defaultTile;
public MPMap()
{
_defaultTile = new MPTile();
_defaultTile.TexLayer = new MPTileTex[4];
//_pDefaultTile->TexLayer[0].btTexNo = UNDERWATER_TEXNO;
//_pDefaultTile->TexLayer[0].btAlphaNo = 15;
//_pDefaultTile->TexLayer[1].btTexNo = 255; // 标示为DefaultTile
//_pDefaultTile->fHeight = UNDERWATER_HEIGHT;
//_pDefaultTile->dwColor = 0xffffffff;
_defaultTile.TexLayer[0].TexNo = 22;
_defaultTile.TexLayer[0].AlphaNo = 15;
_defaultTile.TexLayer[1].TexNo = 255;
_defaultTile.Height = -2.0f;
}
public void Load(BinaryReader reader)
{
_fp = reader;
this._mapHeader = MPMapFileHeader.Load(reader);
Debug.Log($"version: {this._mapHeader.MapFlag}");
SectionCntX = this.Width / SectionWidth;
SecitonCntY = this.Height / SectionHeight;
SectionCnt = SectionCntX * SecitonCntY;
// 读取块的偏移位置
_offsetIdx = new int[SectionCnt];
for (int i = 0; i < _offsetIdx.Length; i++)
_offsetIdx[i] = reader.ReadInt32();
ActiveSectionArray = new MPActiveMapSection[SectionCntX, SecitonCntY];
FullLoading();
}
private void FullLoading()
{
for (int i = 0; i < SectionCnt; i++)
{
int x = i % SectionCntX;
int y = i / SectionCntX;
if (_offsetIdx[i] != 0)
{
LoadSectionData(x, y);
}
}
}
private void LoadSectionData(int sectionX, int sectionY)
{
MPActiveMapSection section = new MPActiveMapSection
{
X = sectionX,
Y = sectionY
};
LoadSectionData(ref section);
ActiveSectionArray[sectionX, sectionY] = section;
}
/// <summary>
/// 读取地图区块数据
/// </summary>
/// <param name="section"></param>
private void LoadSectionData(ref MPActiveMapSection section)
{
int sectionX = section.X;
int sectionY = section.Y;
section.DataOffset = ReadSectionDataOffset(sectionX, sectionY);
if (section.DataOffset == 0)
{
Debug.LogWarning($"空块数据: {sectionX},{sectionY}");
return;
}
// 开始读取tile数据
_fp.BaseStream.Seek(section.DataOffset, SeekOrigin.Begin);
section.TileData = new MPTile[SectionWidth * SectionHeight];
for (int y = 0; y < SectionHeight; y++)
{
for (int x = 0; x < SectionWidth; x++)
{
int idx = GetMPTileIndex(x, y);
MPTile tile = new MPTile();
SNewFileTile fileTile = SNewFileTile.Load(_fp);
// rgb565 to int
short rgb = fileTile.Color;
byte r = (byte)((rgb & 0xf800) >> 8);
byte g = (byte)((rgb & 0x7e0) >> 3);
byte b = (byte)((rgb & 0x1f) << 3);
tile.UniColor = new Color(r / 255f, g / 255f, b / 255f);
tile.TileInfo_5To8(fileTile.btTileInfo, fileTile.dwTileInfo);
tile.Height = (fileTile.Height) * 10f / 100.0f;
tile.IsLand = fileTile.IsLand;
tile.Region = fileTile.Region;
unsafe
{
Span<byte> dst = new Span<byte>(tile.Block, 4);
Span<byte> src = new Span<byte>(fileTile.Block, 4);
src.CopyTo(dst);
}
section.TileData[idx] = tile;
}
}
}
/// <summary>
/// 设置读取区块数据的偏移
/// </summary>
/// <param name="sectionX"></param>
/// <param name="sectionY"></param>
/// <returns></returns>
private int ReadSectionDataOffset(int sectionX, int sectionY)
{
int loc = sectionY * SectionCntX + sectionX;
return _offsetIdx[loc];
}
public int GetMPTileIndex(int x, int y)
{
return SectionWidth * y + x;
}
/// <summary>
/// 通过地图坐标直接获取Tile点
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public MPTile GetTile(int x, int y)
{
// y = Height - y - 1;
int sX = x / SectionWidth;
int sY = y / SectionHeight;
if (ActiveSectionArray.GetLength(0) <= sX || ActiveSectionArray.GetLength(1) <= sY)
return _defaultTile;
MPActiveMapSection section = ActiveSectionArray[sX, sY];
if (section.TileData is not { Length: > 0 }) return _defaultTile;
int tX = x % SectionWidth;
int tY = y % SectionHeight;
int idx = GetMPTileIndex(tX, tY);
if (idx >= section.TileData.Length || idx < 0)
return _defaultTile;
return section.TileData[idx];
}
}
}