Init
This commit is contained in:
100
Assets/MindPowerSdk/Map/MPActiveMapSection.cs
Normal file
100
Assets/MindPowerSdk/Map/MPActiveMapSection.cs
Normal file
@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MindPowerSdk
|
||||
{
|
||||
/// <summary>
|
||||
/// 单一贴图层
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct MPTileTex
|
||||
{
|
||||
public byte TexNo; // 贴图编号
|
||||
public byte AlphaNo; // Alpha图编号
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{TexNo},{AlphaNo}";
|
||||
}
|
||||
|
||||
public byte SetAlphaNo(byte alphaNo, bool reset = false)
|
||||
{
|
||||
if (reset)
|
||||
{
|
||||
this.AlphaNo = alphaNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.AlphaNo |= alphaNo;
|
||||
}
|
||||
|
||||
return alphaNo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
MPTileTex TexLayer[4]; // 最多4层重叠
|
||||
DWORD dwColor; // 左上角第一个顶点的颜色
|
||||
short sRegion; // 区域属性
|
||||
BYTE btIsland; // 岛屿属性
|
||||
BYTE btBlock[4]; // 4个分格的障碍记录
|
||||
|
||||
float fHeight; // 左上角第一个顶点的高度
|
||||
|
||||
//lemon add@2004.10.18
|
||||
DWORD dwTColor; // 临时顶点的颜色
|
||||
DWORD dwXColor; // 混合后的颜色
|
||||
*
|
||||
*/
|
||||
public unsafe struct MPTile
|
||||
{
|
||||
public MPTileTex[] TexLayer; // 最多4层重叠
|
||||
public short Color; // 左上角第一个顶点的颜色
|
||||
public short Region; // 区域属性
|
||||
public byte IsLand; // 岛屿属性
|
||||
public fixed byte Block[4]; // 4个分格的障碍记录
|
||||
|
||||
public float Height; // 左上角第一个顶点的高度
|
||||
|
||||
public int TColor; // 临时顶点颜色
|
||||
public int XColor; // 混合后的颜色
|
||||
|
||||
|
||||
public Color UniColor;
|
||||
|
||||
public void TileInfo_5To8(byte bt, uint dwNew)
|
||||
{
|
||||
byte* pbtTile = stackalloc byte[8];
|
||||
|
||||
pbtTile[0] = bt;
|
||||
pbtTile[1] = 15;
|
||||
pbtTile[2] = (byte)(dwNew >> 26);
|
||||
pbtTile[3] = (byte)((dwNew >> 22) & 0x000F);
|
||||
pbtTile[4] = (byte)((dwNew >> 16) & 63);
|
||||
pbtTile[5] = (byte)((dwNew >> 12) & 0x000F);
|
||||
pbtTile[6] = (byte)((dwNew >> 6) & 63);
|
||||
pbtTile[7] = (byte)((dwNew >> 2) & 0x000F);
|
||||
|
||||
this.TexLayer = new MPTileTex[4];
|
||||
for (int i = 0; i < 8; i += 2)
|
||||
{
|
||||
this.TexLayer[i / 2].TexNo = pbtTile[i];
|
||||
this.TexLayer[i / 2].AlphaNo = pbtTile[i + 1];
|
||||
}
|
||||
|
||||
//Debug.Log($"{TexLayer[0]}|{TexLayer[1]}|{TexLayer[2]}|{TexLayer[3]}");
|
||||
}
|
||||
}
|
||||
|
||||
public struct MPActiveMapSection
|
||||
{
|
||||
public MPTile[] TileData;
|
||||
public int X, Y; // MapSection所在的位置
|
||||
public int ActiveTime; // 最后一次使用的时间
|
||||
public int DataOffset; // 文件数据指针位置 = 0, 表示没有数据
|
||||
}
|
||||
}
|
11
Assets/MindPowerSdk/Map/MPActiveMapSection.cs.meta
generated
Normal file
11
Assets/MindPowerSdk/Map/MPActiveMapSection.cs.meta
generated
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c2d672641ccf5748bfcfb41532562a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
235
Assets/MindPowerSdk/Map/MPMap.cs
Normal file
235
Assets/MindPowerSdk/Map/MPMap.cs
Normal file
@ -0,0 +1,235 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace MindPowerSdk
|
||||
{
|
||||
public partial class MPMap
|
||||
{
|
||||
public const float SEA_LEVEL = 0.0f;
|
||||
|
||||
private static readonly int[,] Offset =
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ 1, 0 },
|
||||
{ 0, 1 },
|
||||
{ 1, 1 }
|
||||
};
|
||||
|
||||
private MPTile GetGroupTile(int x, int y, int no)
|
||||
{
|
||||
return GetTile(x + Offset[no, 0], y + Offset[no, 1]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取地形的高度
|
||||
/// </summary>
|
||||
/// <param name="fX"></param>
|
||||
/// <param name="fY"></param>
|
||||
/// <returns></returns>
|
||||
public float GetHeight(float fX, float fY)
|
||||
{
|
||||
// 将浮点坐标转换为整数坐标(取整)
|
||||
int nX = (int)fX;
|
||||
int nY = (int)fY;
|
||||
|
||||
// 计算四个角点的坐标(构成一个单位矩形)
|
||||
float fx1 = (float)nX;
|
||||
float fx2 = (float)nX + 1;
|
||||
float fy1 = (float)nY;
|
||||
float fy2 = (float)nY + 1;
|
||||
|
||||
// 初始化四个顶点的高度(默认海平面)
|
||||
float[] fHeight = new float[4] { SEA_LEVEL, SEA_LEVEL, SEA_LEVEL, SEA_LEVEL };
|
||||
|
||||
// 获取基准瓦片
|
||||
MPTile pTile = GetTile(nX, nY);
|
||||
// 遍历四个顶点获取实际高度
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
MPTile pCurTile = GetGroupTile(nX, nY, i);
|
||||
fHeight[i] = pCurTile.Height;
|
||||
}
|
||||
|
||||
// 构建四个三维顶点
|
||||
Vector3 v0 = new Vector3(fx1, fy1, fHeight[0]);
|
||||
Vector3 v1 = new Vector3(fx2, fy1, fHeight[1]);
|
||||
Vector3 v2 = new Vector3(fx1, fy2, fHeight[2]);
|
||||
Vector3 v3 = new Vector3(fx2, fy2, fHeight[3]);
|
||||
|
||||
// 创建射线(从高处垂直向下)
|
||||
Vector3 vOrig = new Vector3(fX, fY, 20.0f); // 起点
|
||||
Vector3 vDir = new Vector3(0, 0, -1); // 方向向下
|
||||
float u, v; // 用于存储交点参数
|
||||
|
||||
Vector3 vPickPos;
|
||||
// 检测与第一个三角形(v0-v1-v2)的相交
|
||||
if (IntersectTri(v0, v1, v2, vOrig, vDir, out u, out v))
|
||||
{
|
||||
vPickPos = v0 + u * (v1 - v0) + v * (v2 - v0);
|
||||
return vPickPos.z; // 返回交点的Z值(高度)
|
||||
}
|
||||
|
||||
// 检测与第二个三角形(v2-v1-v3)的相交
|
||||
if (IntersectTri(v2, v1, v3, vOrig, vDir, out u, out v))
|
||||
{
|
||||
vPickPos = v2 + u * (v1 - v2) + v * (v3 - v2);
|
||||
return vPickPos.z;
|
||||
}
|
||||
|
||||
// 无交点返回0
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// Unity版本的三角形射线相交检测
|
||||
bool IntersectTri(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 origin, Vector3 direction, out float u, out float v)
|
||||
{
|
||||
u = v = 0;
|
||||
Vector3 edge1 = v1 - v0;
|
||||
Vector3 edge2 = v2 - v0;
|
||||
|
||||
// 计算行列式
|
||||
Vector3 pvec = Vector3.Cross(direction, edge2);
|
||||
float det = Vector3.Dot(edge1, pvec);
|
||||
|
||||
// 背面剔除(det > 0 可改为 det < 0 如果需要双面检测)
|
||||
if (det < Mathf.Epsilon)
|
||||
return false;
|
||||
|
||||
// 计算U参数并测试范围
|
||||
Vector3 tvec = origin - v0;
|
||||
u = Vector3.Dot(tvec, pvec);
|
||||
if (u < 0 || u > det) return false;
|
||||
|
||||
// 计算V参数并测试范围
|
||||
Vector3 qvec = Vector3.Cross(tvec, edge1);
|
||||
v = Vector3.Dot(direction, qvec);
|
||||
if (v < 0 || u + v > det) return false;
|
||||
|
||||
// 归一化参数
|
||||
float invDet = 1.0f / det;
|
||||
u *= invDet;
|
||||
v *= invDet;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回结束位置与矩形大小
|
||||
/// </summary>
|
||||
/// <param name="startX"></param>
|
||||
/// <param name="startY"></param>
|
||||
/// <param name="showSize"></param>
|
||||
/// <returns></returns>
|
||||
public RectInt GetRect(short startX, short startY, int showSize)
|
||||
{
|
||||
int endX = Mathf.Min(startX + showSize, Width);
|
||||
int endY = Mathf.Min(startY + showSize, Height);
|
||||
|
||||
// 本次宽高
|
||||
int width = endX - startX;
|
||||
int height = endY - startY;
|
||||
|
||||
return new RectInt(endX, endY, width, height);
|
||||
}
|
||||
|
||||
public Mesh GenMesh(short startX, short startY, int showSize)
|
||||
{
|
||||
RectInt rect = GetRect(startX, startY, showSize);
|
||||
|
||||
// 顶点
|
||||
int verticesNum = (rect.width) * (rect.height) * 4;
|
||||
Vector3[] vertices = new Vector3[verticesNum];
|
||||
int[] triangles = new int[verticesNum * 6];
|
||||
Vector2[] uv0 = new Vector2[verticesNum];
|
||||
Vector2[] uv2 = new Vector2[verticesNum];
|
||||
int vertIdx = 0;
|
||||
int triIdx = 0;
|
||||
|
||||
for (short y = startY; y < rect.y; y++)
|
||||
{
|
||||
for (short x = startX; x < rect.x; x++)
|
||||
{
|
||||
// 添加4个顶点
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
MPTile tile = GetGroupTile(x, y, i);
|
||||
vertices[vertIdx + i] = new Vector3(x + Offset[i, 0], tile.Height, (y + Offset[i, 1]) * -1);
|
||||
// Debug.Log($"{x},{y}");
|
||||
|
||||
// uv 整个mesh映射到一张贴图上
|
||||
int rx = x - startX;
|
||||
// int ry = rect.y - y - 2;
|
||||
int ry = y - startY + 1;
|
||||
uv0[vertIdx + i] = new Vector2((rx + Offset[i, 0]) / (float)rect.width, (ry + Offset[i, 1]) * -1 / (float)rect.height);
|
||||
uv2[vertIdx + i] = new Vector2(Offset[i, 0], Offset[i, 1] * -1);
|
||||
}
|
||||
|
||||
triangles[triIdx + 0] = vertIdx + 2;
|
||||
triangles[triIdx + 1] = vertIdx + 0;
|
||||
triangles[triIdx + 2] = vertIdx + 3;
|
||||
|
||||
triangles[triIdx + 3] = vertIdx + 0;
|
||||
triangles[triIdx + 4] = vertIdx + 1;
|
||||
triangles[triIdx + 5] = vertIdx + 3;
|
||||
|
||||
vertIdx += 4;
|
||||
triIdx += 6;
|
||||
}
|
||||
}
|
||||
|
||||
Mesh mesh = new Mesh();
|
||||
mesh.SetVertices(vertices);
|
||||
mesh.SetTriangles(triangles, 0);
|
||||
mesh.SetUVs(0, uv0);
|
||||
mesh.SetUVs(2, uv2);
|
||||
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
public (Texture2D, Texture2D) GenTxtNoTexture(short startX, short startY, int showSize)
|
||||
{
|
||||
RectInt rect = GetRect(startX, startY, showSize);
|
||||
|
||||
Texture2D texture1 = new Texture2D(rect.width, rect.height, TextureFormat.RGBA32, false, true); // 贴图值: texNo
|
||||
texture1.filterMode = FilterMode.Point;
|
||||
|
||||
Texture2D texture2 = new Texture2D(rect.width, rect.height, TextureFormat.RGBA32, false, true); // 遮罩值:alphaNo
|
||||
texture2.filterMode = FilterMode.Point;
|
||||
|
||||
for (short y = startY; y < rect.y; y++)
|
||||
{
|
||||
for (short x = startX; x < rect.x; x++)
|
||||
{
|
||||
MPTile tile = GetTile(x, y);
|
||||
|
||||
// 4层数据
|
||||
float r = (tile.TexLayer[0].TexNo - 1) / 64f;
|
||||
float g = (tile.TexLayer[1].TexNo - 1) / 64f;
|
||||
float b = (tile.TexLayer[2].TexNo - 1) / 64f;
|
||||
float a = (tile.TexLayer[3].TexNo - 1) / 64f;
|
||||
|
||||
int rx = x - startX;
|
||||
int ry = rect.y - 1 - y;
|
||||
texture1.SetPixel(rx, ry, new Color(r, g, b, a));
|
||||
|
||||
var alphaNo = new Color(
|
||||
(tile.TexLayer[0].AlphaNo - 1) / 16f,
|
||||
(tile.TexLayer[1].AlphaNo - 1) / 16f,
|
||||
(tile.TexLayer[2].AlphaNo - 1) / 16f,
|
||||
(tile.TexLayer[3].AlphaNo - 1) / 16f);
|
||||
texture2.SetPixel(rx, ry, alphaNo);
|
||||
|
||||
if (alphaNo.r > 48 || alphaNo.g > 48 || alphaNo.b > 48 || alphaNo.a > 48)
|
||||
{
|
||||
Debug.LogError($"{rx},{ry}|{alphaNo}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
texture1.Apply();
|
||||
texture2.Apply();
|
||||
|
||||
return (texture1, texture2);
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/MindPowerSdk/Map/MPMap.cs.meta
generated
Normal file
11
Assets/MindPowerSdk/Map/MPMap.cs.meta
generated
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16ac39916dae5c146982e3e6194888e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
194
Assets/MindPowerSdk/Map/MPMap.data.cs
Normal file
194
Assets/MindPowerSdk/Map/MPMap.data.cs
Normal file
@ -0,0 +1,194 @@
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/MindPowerSdk/Map/MPMap.data.cs.meta
generated
Normal file
11
Assets/MindPowerSdk/Map/MPMap.data.cs.meta
generated
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d48cf981a8a35d488fa8efbbc1d0e56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
50
Assets/MindPowerSdk/Map/MPMapFileHeader.cs
Normal file
50
Assets/MindPowerSdk/Map/MPMapFileHeader.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MindPowerSdk
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct MPMapFileHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// 类型标识 = 780624
|
||||
/// </summary>
|
||||
public int MapFlag { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地图宽度
|
||||
/// </summary>
|
||||
public int Width { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地图高度
|
||||
/// </summary>
|
||||
public int Height { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 每个Section(部分)宽度
|
||||
/// </summary>
|
||||
public int SectionWidth { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 每个Section(部分)高度
|
||||
/// </summary>
|
||||
public int SectionHeight { get; private set; }
|
||||
|
||||
public static MPMapFileHeader Load(BinaryReader reader)
|
||||
{
|
||||
MPMapFileHeader header = default;
|
||||
|
||||
header.MapFlag = reader.ReadInt32();
|
||||
header.Width = reader.ReadInt32();
|
||||
header.Height = reader.ReadInt32();
|
||||
header.SectionWidth = reader.ReadInt32();
|
||||
header.SectionHeight = reader.ReadInt32();
|
||||
|
||||
return header;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/MindPowerSdk/Map/MPMapFileHeader.cs.meta
generated
Normal file
11
Assets/MindPowerSdk/Map/MPMapFileHeader.cs.meta
generated
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01c3951dd660b8c4ebdec0bc39a0d925
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
34
Assets/MindPowerSdk/Map/SNewFileTile.cs
Normal file
34
Assets/MindPowerSdk/Map/SNewFileTile.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MindPowerSdk
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public unsafe struct SNewFileTile
|
||||
{
|
||||
// DWORD dwTileInfo; // 保存3个layer的tex no和alpha no
|
||||
// BYTE btTileInfo; // 最下层的tex no
|
||||
// short sColor; // 32bit的颜色保存为565
|
||||
// char cHeight; // 每10cm为一级来保存高度
|
||||
// short sRegion;
|
||||
// BYTE btIsland;
|
||||
// BYTE btBlock[4];
|
||||
|
||||
public uint dwTileInfo;
|
||||
public byte btTileInfo;
|
||||
public short Color;
|
||||
public sbyte Height;
|
||||
public short Region;
|
||||
public byte IsLand;
|
||||
public fixed byte Block[4];
|
||||
|
||||
public static SNewFileTile Load(BinaryReader reader)
|
||||
{
|
||||
SNewFileTile s = new SNewFileTile();
|
||||
Span<byte> bytes = new Span<byte>(&s, sizeof(SNewFileTile));
|
||||
reader.Read(bytes);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/MindPowerSdk/Map/SNewFileTile.cs.meta
generated
Normal file
11
Assets/MindPowerSdk/Map/SNewFileTile.cs.meta
generated
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7de4f04a34c974247b83bb95ce85ee20
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
157
Assets/MindPowerSdk/Map/SceneObjFile.cs
Normal file
157
Assets/MindPowerSdk/Map/SceneObjFile.cs
Normal file
@ -0,0 +1,157 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using MindPowerSdk;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MindPowerSdk
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
public struct SceneObjInfo
|
||||
{
|
||||
public ushort TypeId; // 高2位是type(0: 场景物件, 1: 特效物件), 其余是ID
|
||||
public int X; // 相对坐标
|
||||
public int Y;
|
||||
|
||||
public short HeightOff;
|
||||
public short YawAngle;
|
||||
public short Scale; // 保留未使用
|
||||
|
||||
public short GetTypeId()
|
||||
{
|
||||
return (short)(TypeId >> 14);
|
||||
}
|
||||
|
||||
public short GetID()
|
||||
{
|
||||
return (short)(TypeId & 0x3FFF);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"type={GetTypeId()},id={GetID()},x={X},y={Y},height_off={HeightOff},yaw_angle={YawAngle},scale={Scale}";
|
||||
}
|
||||
}
|
||||
|
||||
public class SceneObjFile
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件头
|
||||
/// </summary>
|
||||
public struct Header
|
||||
{
|
||||
public string Title; // "HF Object File!" char[16]
|
||||
public int Version;
|
||||
public int FileSize;
|
||||
|
||||
public int SectionCntX; // 地图的横向区域数
|
||||
public int SectionCntY; // 地图的纵向区域数
|
||||
|
||||
public int SectionWidth; // 区域的宽度(单位:Tile)
|
||||
public int SectionHeight; // 区域的高度(单位:Tile)
|
||||
public int SectionObjNum; // 区域允许的最大物件数
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用来索引文件中对象的数据
|
||||
/// </summary>
|
||||
public struct SSectionIndex
|
||||
{
|
||||
public int ObjInfoPos;
|
||||
public int ObjNum;
|
||||
}
|
||||
|
||||
|
||||
public Header FileHeader { get; private set; }
|
||||
|
||||
SSectionIndex[,] sectionIndex;
|
||||
|
||||
public List<SceneObjInfo>[,] objInfos;
|
||||
|
||||
public unsafe int Load(string obj_file)
|
||||
{
|
||||
FileStream fs = File.OpenRead(obj_file);
|
||||
BinaryReader r = new BinaryReader(fs);
|
||||
|
||||
long size = r.BaseStream.Length;
|
||||
|
||||
Header s = new Header();
|
||||
s.Title = Encoding.ASCII.GetString(r.ReadBytes(16));
|
||||
s.Version = r.ReadInt32();
|
||||
s.FileSize = r.ReadInt32(); // 实际是32位
|
||||
|
||||
s.SectionCntX = r.ReadInt32();
|
||||
s.SectionCntY = r.ReadInt32();
|
||||
|
||||
s.SectionWidth = r.ReadInt32();
|
||||
s.SectionHeight = r.ReadInt32();
|
||||
s.SectionObjNum = r.ReadInt32();
|
||||
|
||||
FileHeader = s;
|
||||
|
||||
Debug.Log(JsonUtility.ToJson(s));
|
||||
|
||||
if (s.FileSize != size)
|
||||
{
|
||||
Debug.LogWarning($"{obj_file} 文件szie不匹配: {s.FileSize} != {size}");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s.Version != 600)
|
||||
{
|
||||
Debug.LogWarning($"{obj_file} 版本只支持600: 当前是={s.Version}");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 读取索引信息
|
||||
sectionIndex = new SSectionIndex[s.SectionCntX, s.SectionCntY];
|
||||
for (int y = 0; y < s.SectionCntY; y++)
|
||||
{
|
||||
for (int x = 0; x < s.SectionCntX; x++)
|
||||
{
|
||||
SSectionIndex data = new SSectionIndex();
|
||||
data.ObjInfoPos = r.ReadInt32();
|
||||
data.ObjNum = r.ReadInt32();
|
||||
sectionIndex[x, y] = data;
|
||||
|
||||
if (data.ObjNum != 0)
|
||||
Debug.Log(JsonUtility.ToJson(data));
|
||||
}
|
||||
}
|
||||
|
||||
// 读取场景物体
|
||||
objInfos = new List<SceneObjInfo>[s.SectionCntX, s.SectionCntY];
|
||||
for (int y = 0; y < s.SectionCntY; y++)
|
||||
{
|
||||
for (int x = 0; x < s.SectionCntX; x++)
|
||||
{
|
||||
SSectionIndex idx = sectionIndex[x, y];
|
||||
if (idx.ObjNum == 0)
|
||||
continue;
|
||||
|
||||
var list = objInfos[x, y] ??= new List<SceneObjInfo>();
|
||||
|
||||
r.BaseStream.Seek(idx.ObjInfoPos, SeekOrigin.Begin);
|
||||
|
||||
for (int i = 0; i < idx.ObjNum; i++)
|
||||
{
|
||||
byte[] tmpBytes = r.ReadBytes(sizeof(SceneObjInfo));
|
||||
SceneObjInfo sceneObjInfo = StructReader.ReadStructFromArray<SceneObjInfo>(tmpBytes);
|
||||
|
||||
// 转成绝对坐标
|
||||
int sectionX = x * s.SectionWidth * 100;
|
||||
int sectionY = y * s.SectionHeight * 100;
|
||||
sceneObjInfo.X += sectionX;
|
||||
sceneObjInfo.Y += sectionY;
|
||||
|
||||
list.Add(sceneObjInfo);
|
||||
Debug.Log(sceneObjInfo.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/MindPowerSdk/Map/SceneObjFile.cs.meta
generated
Normal file
11
Assets/MindPowerSdk/Map/SceneObjFile.cs.meta
generated
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74622940af1063046bc3832a354b4566
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user