2025-06-15 22:06:57 +08:00
|
|
|
|
using Cysharp.Threading.Tasks;
|
2025-06-16 21:26:36 +08:00
|
|
|
|
using HxGame.Data;
|
2025-06-14 13:46:24 +08:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
2025-07-25 15:36:10 +08:00
|
|
|
|
using System.Drawing;
|
2025-08-22 16:02:14 +08:00
|
|
|
|
using System.Drawing.Imaging;
|
2025-06-14 13:46:24 +08:00
|
|
|
|
using System.IO;
|
2025-08-22 16:02:14 +08:00
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Runtime.Remoting.Metadata.W3cXsd2001;
|
2025-06-16 00:15:41 +08:00
|
|
|
|
using System.Threading;
|
2025-06-14 13:46:24 +08:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
public partial class MapManager : MonoBehaviour
|
2025-06-16 00:15:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
[SerializeField]
|
2025-06-21 01:29:18 +08:00
|
|
|
|
private Transform mapRegionParent;
|
|
|
|
|
|
|
|
|
|
|
|
public Transform mapGridParent;
|
|
|
|
|
|
public Transform mapAreaParent;
|
2025-06-22 18:23:47 +08:00
|
|
|
|
public Transform mapMonsterArea;
|
|
|
|
|
|
public Transform mapNPCArea;
|
|
|
|
|
|
public Transform mapTeleportArea;
|
|
|
|
|
|
public Transform mapReliveArea;
|
2025-07-18 22:28:40 +08:00
|
|
|
|
public Transform mapAudioTrigger;
|
2025-08-22 16:02:14 +08:00
|
|
|
|
public Dictionary<string, (int maxRow, int maxCol,int maxNum)> allMaps = new Dictionary<string, (int maxRow, int maxCol, int maxNum)>();
|
2025-06-16 23:59:28 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// <20><>ǰ<EFBFBD><C7B0>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>
|
|
|
|
|
|
/// </summary>
|
2025-06-17 00:23:38 +08:00
|
|
|
|
public MapRegions _curMapRegions;
|
2025-06-16 23:59:28 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="mapId"></param>
|
|
|
|
|
|
public void SaveRegionXML()
|
2025-06-16 21:26:36 +08:00
|
|
|
|
{
|
2025-06-16 23:59:28 +08:00
|
|
|
|
int mapId = _curOpenMapId;
|
|
|
|
|
|
if (!allMaps.TryGetValue(_curOpenMapId.ToString(), out var curMap))
|
2025-06-16 21:26:36 +08:00
|
|
|
|
{
|
2025-06-16 23:59:28 +08:00
|
|
|
|
UIWindow.Instance.ShowMessage($"û<><C3BB>ɨ<EFBFBD>赽<EFBFBD><E8B5BD>ǰ<EFBFBD><C7B0>ͼ [{_curOpenMapId}]");
|
2025-06-16 21:26:36 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-06-19 13:32:33 +08:00
|
|
|
|
_curMapRegions?.SaveXML(mapId);
|
2025-07-25 15:36:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SaveAtlasToFile()
|
|
|
|
|
|
{
|
2025-08-22 16:02:14 +08:00
|
|
|
|
if (MapManager.Instance.map == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
UIWindow.Instance.ShowMessage("<22><><EFBFBD>ȴ<C8B4>ͼ");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-07-25 15:36:10 +08:00
|
|
|
|
int atlasWidth = _curMapRegions.regionRowNum * (int)_curMapRegions.regionWidth;
|
|
|
|
|
|
int atlasHeight = _curMapRegions.regionColNum * (int)_curMapRegions.regionHeight;
|
|
|
|
|
|
if (atlasWidth < 8192)
|
|
|
|
|
|
{
|
|
|
|
|
|
SaveAtlasToFileSmall();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// ʹ<><CAB9><EFBFBD>ڴ<EFBFBD><DAB4>Ż<EFBFBD><C5BB><EFBFBD>Bitmap<61><70><EFBFBD><EFBFBD>
|
|
|
|
|
|
Bitmap atlas = new Bitmap(atlasWidth, atlasHeight, PixelFormat.Format24bppRgb);
|
|
|
|
|
|
|
|
|
|
|
|
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(atlas))
|
|
|
|
|
|
{
|
|
|
|
|
|
g.Transform = new System.Drawing.Drawing2D.Matrix(1, 0, 0, -1, 0, atlas.Height);
|
|
|
|
|
|
for (int row = 0; row < _curMapRegions.regionRowNum; row++)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int col = 0; col < _curMapRegions.regionColNum; col++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Texture2D tileTex = _curMapRegions.regions[row, col].texture;
|
|
|
|
|
|
if (tileTex == null) continue;
|
|
|
|
|
|
|
|
|
|
|
|
Bitmap tileBitmap = TextureToBitmap(tileTex);
|
|
|
|
|
|
g.DrawImage(
|
|
|
|
|
|
tileBitmap,
|
|
|
|
|
|
row * (int)_curMapRegions.regionWidth,
|
|
|
|
|
|
col * (int)_curMapRegions.regionHeight
|
|
|
|
|
|
);
|
|
|
|
|
|
tileBitmap.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>JPG<50><47><EFBFBD><EFBFBD>Alphaʱ<61><CAB1>
|
|
|
|
|
|
string outputPath = $"{PathUtil.GetBigMapPath(_curOpenMapId)}/map_{_curOpenMapId}.jpg";
|
|
|
|
|
|
atlas.Save(outputPath, ImageFormat.Jpeg);
|
|
|
|
|
|
atlas.Dispose();
|
|
|
|
|
|
|
|
|
|
|
|
Debug.Log($"<22><><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD>ߴ<EFBFBD>: {atlasWidth}x{atlasHeight}");
|
|
|
|
|
|
UIWindow.Instance.ShowMessage("<22><>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Bitmap TextureToBitmap(Texture2D texture)
|
|
|
|
|
|
{
|
|
|
|
|
|
bool hasAlpha = texture.GetPixels().Any(c => c.a < 1f);
|
|
|
|
|
|
Bitmap bitmap = new Bitmap(
|
|
|
|
|
|
texture.width,
|
|
|
|
|
|
texture.height,
|
|
|
|
|
|
hasAlpha ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
BitmapData data = bitmap.LockBits(
|
|
|
|
|
|
new Rectangle(0, 0, texture.width, texture.height),
|
|
|
|
|
|
ImageLockMode.WriteOnly,
|
|
|
|
|
|
bitmap.PixelFormat
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
byte[] bytes = new byte[texture.width * texture.height * (hasAlpha ? 4 : 3)];
|
|
|
|
|
|
UnityEngine.Color[] pixels = texture.GetPixels();
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < pixels.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
bytes[i * (hasAlpha ? 4 : 3)] = (byte)(pixels[i].b * 255); // B
|
|
|
|
|
|
bytes[i * (hasAlpha ? 4 : 3) + 1] = (byte)(pixels[i].g * 255); // G
|
|
|
|
|
|
bytes[i * (hasAlpha ? 4 : 3) + 2] = (byte)(pixels[i].r * 255); // R
|
|
|
|
|
|
if (hasAlpha) bytes[i * 4 + 3] = (byte)(pixels[i].a * 255); // A
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
System.Runtime.InteropServices.Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);
|
|
|
|
|
|
bitmap.UnlockBits(data);
|
|
|
|
|
|
return bitmap;
|
|
|
|
|
|
}
|
|
|
|
|
|
public void SaveAtlasToFileSmall()
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>ijߴ<C4B3>
|
|
|
|
|
|
int atlasWidth = _curMapRegions.regionRowNum * (int)_curMapRegions.regionWidth;
|
|
|
|
|
|
int atlasHeight = _curMapRegions.regionColNum * (int)_curMapRegions.regionHeight;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>յĴ<D5B5>ͼ
|
|
|
|
|
|
Texture2D atlas = new Texture2D(atlasWidth, atlasHeight);
|
|
|
|
|
|
atlas.filterMode = FilterMode.Bilinear; // <20><><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сͼ<D0A1><CDBC><EFBFBD>ϲ<EFBFBD>
|
|
|
|
|
|
for (int row = 0; row < _curMapRegions.regionRowNum; row++)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int col = 0; col < _curMapRegions.regionColNum; col++)
|
|
|
|
|
|
{
|
|
|
|
|
|
HxGame.Data.Region region = _curMapRegions.regions[row, col];
|
|
|
|
|
|
Texture2D tileTex = region.texture; // <20><><EFBFBD><EFBFBD>Сͼ<D0A1><CDBC><EFBFBD><EFBFBD>
|
|
|
|
|
|
atlas.SetPixels(
|
|
|
|
|
|
row * (int)_curMapRegions.regionWidth,
|
|
|
|
|
|
col * (int)_curMapRegions.regionHeight,
|
|
|
|
|
|
(int)_curMapRegions.regionWidth,
|
|
|
|
|
|
(int)_curMapRegions.regionHeight,
|
|
|
|
|
|
tileTex.GetPixels()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
atlas.Apply(); // Ӧ<><D3A6><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>
|
|
|
|
|
|
byte[] pngData = atlas.EncodeToJPG();
|
|
|
|
|
|
File.WriteAllBytes($"{PathUtil.GetBigMapPath(_curOpenMapId)}/map_{_curOpenMapId}.jpg", pngData);
|
|
|
|
|
|
UIWindow.Instance.ShowMessage("<22><>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>");
|
2025-06-16 21:26:36 +08:00
|
|
|
|
}
|
2025-06-16 23:59:28 +08:00
|
|
|
|
public void LoadMapRegionSprites(int mapId)
|
2025-06-15 20:14:45 +08:00
|
|
|
|
{
|
2025-08-22 16:02:14 +08:00
|
|
|
|
OldRegionSprites(mapId);
|
|
|
|
|
|
}
|
|
|
|
|
|
public void OldRegionSprites(int mapId)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!allMaps.TryGetValue(mapId.ToString(), out var mapInfo))
|
2025-06-16 00:15:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
UIWindow.Instance.ShowMessage("<22><>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>ڡ<EFBFBD><DAA1><EFBFBD><EFBFBD><EFBFBD>");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
int mapRownum = mapInfo.maxRow;
|
|
|
|
|
|
int mapColumn = mapInfo.maxCol;
|
2025-06-16 23:59:28 +08:00
|
|
|
|
_curMapRegions = new MapRegions();
|
|
|
|
|
|
_curOpenMapId = mapId;
|
|
|
|
|
|
_curMapRegions.regionRowNum = mapRownum;
|
|
|
|
|
|
_curMapRegions.regionColNum = mapColumn;
|
|
|
|
|
|
_curMapRegions.regionWidth = PicMapPixel;
|
|
|
|
|
|
_curMapRegions.regionHeight = PicMapPixel;
|
|
|
|
|
|
_curMapRegions.cellWidthPixel = widthPixel;
|
|
|
|
|
|
_curMapRegions.cellHeightPixel = heightPixel;
|
2025-07-25 15:36:10 +08:00
|
|
|
|
_curMapRegions.regions = new HxGame.Data.Region[mapRownum, mapColumn];
|
2025-06-27 01:08:56 +08:00
|
|
|
|
|
|
|
|
|
|
int maxRow = mapColumn;
|
|
|
|
|
|
int maxCol = mapRownum;
|
2025-06-19 13:32:33 +08:00
|
|
|
|
float jpgscenew = PicMapPixel / 100.0f;
|
2025-06-27 01:08:56 +08:00
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < mapRownum; row++) //14 * 11
|
2025-06-15 20:14:45 +08:00
|
|
|
|
{
|
|
|
|
|
|
for (int col = 0; col < mapColumn; col++)
|
|
|
|
|
|
{
|
2025-06-27 01:08:56 +08:00
|
|
|
|
string filename = $"v{mapId}_r{mapColumn - col}_c{row + 1}"; // <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>v1000_r11_c1.jpg
|
2025-07-21 18:38:50 +08:00
|
|
|
|
string spPath = PathUtil.GetMapTexure(mapId, filename, "jpg");
|
2025-06-15 20:14:45 +08:00
|
|
|
|
GameObject obj = new GameObject(filename);
|
2025-06-21 01:29:18 +08:00
|
|
|
|
obj.transform.SetParent(mapRegionParent);
|
2025-06-15 20:14:45 +08:00
|
|
|
|
SpriteRenderer sr = obj.AddComponent<SpriteRenderer>();
|
2025-06-27 01:08:56 +08:00
|
|
|
|
float x = row * jpgscenew;
|
|
|
|
|
|
float y = col * jpgscenew;
|
2025-06-15 20:14:45 +08:00
|
|
|
|
obj.transform.position = new Vector2(x, y);
|
2025-07-25 15:36:10 +08:00
|
|
|
|
_curMapRegions.regions[row, col] = new HxGame.Data.Region();
|
2025-06-16 23:59:28 +08:00
|
|
|
|
_curMapRegions.regions[row, col].indexX = row;
|
|
|
|
|
|
_curMapRegions.regions[row, col].indexY = col;
|
2025-07-25 15:36:10 +08:00
|
|
|
|
multithreadLoadTextrue(spPath, sr, _curMapRegions.regions[row, col]);
|
2025-06-27 01:08:56 +08:00
|
|
|
|
_curMapRegions.regions[row, col].regionName = filename;
|
2025-08-22 16:02:14 +08:00
|
|
|
|
}
|
2025-06-15 20:14:45 +08:00
|
|
|
|
}
|
2025-06-16 23:59:28 +08:00
|
|
|
|
MapManager.Instance.ReseCamera(jpgscenew * mapColumn, jpgscenew * mapRownum);
|
2025-06-15 20:14:45 +08:00
|
|
|
|
}
|
2025-06-16 00:15:41 +08:00
|
|
|
|
public void ClearMapRegions()
|
|
|
|
|
|
{
|
|
|
|
|
|
ClearMapGrid();
|
2025-06-21 01:29:18 +08:00
|
|
|
|
foreach (Transform child in mapRegionParent)
|
2025-06-16 00:15:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
Destroy(child.gameObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-19 01:31:00 +08:00
|
|
|
|
|
2025-07-10 13:45:07 +08:00
|
|
|
|
public void CreateObs(int mapid)
|
2025-06-19 01:31:00 +08:00
|
|
|
|
{
|
|
|
|
|
|
if(_curMapRegions == null) return;
|
2025-06-21 01:29:18 +08:00
|
|
|
|
float jpgscenew = PicMapPixel / 100.0f;
|
2025-07-10 13:45:07 +08:00
|
|
|
|
MapManager.Instance.GenerateMap(mapid, jpgscenew * _curMapRegions.regionRowNum, jpgscenew * _curMapRegions.regionColNum, _curMapRegions.cellWidthPixel / 100.0f, _curMapRegions.cellHeightPixel / 100.0f);
|
2025-06-19 01:31:00 +08:00
|
|
|
|
}
|
2025-07-25 15:36:10 +08:00
|
|
|
|
private async void multithreadLoadTextrue(string fullPath,SpriteRenderer sr, HxGame.Data.Region region)
|
2025-06-16 00:15:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
var texture = await loadASyncTexture2D(fullPath, this.GetCancellationTokenOnDestroy());
|
|
|
|
|
|
if (texture != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
sr.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero, 100f);
|
|
|
|
|
|
}
|
2025-07-25 15:36:10 +08:00
|
|
|
|
region.texture = texture;
|
2025-06-16 00:15:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private UniTask<Texture2D> loadASyncTexture2D(string fullPath,CancellationToken token)
|
|
|
|
|
|
{
|
|
|
|
|
|
return UniTask.RunOnThreadPool(async () =>
|
2025-06-15 20:14:45 +08:00
|
|
|
|
{
|
2025-06-16 00:15:41 +08:00
|
|
|
|
if (!File.Exists(fullPath))
|
2025-06-15 20:14:45 +08:00
|
|
|
|
{
|
2025-06-16 00:15:41 +08:00
|
|
|
|
Debug.LogError($"File not found: {fullPath}");
|
|
|
|
|
|
return null;
|
2025-06-15 20:14:45 +08:00
|
|
|
|
}
|
2025-06-16 00:15:41 +08:00
|
|
|
|
// <20><><EFBFBD>̳߳<DFB3><CCB3><EFBFBD><EFBFBD>첽<EFBFBD><ECB2BD>ȡ<EFBFBD>ļ<EFBFBD>
|
|
|
|
|
|
byte[] bytes = await File.ReadAllBytesAsync(fullPath, token);
|
|
|
|
|
|
// <20>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̴߳<DFB3><CCB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
await UniTask.Yield(PlayerLoopTiming.Update);
|
|
|
|
|
|
Texture2D texture = new Texture2D(2, 2); // <20><>ʼ<EFBFBD><CABC>С
|
|
|
|
|
|
if (texture.LoadImage(bytes))
|
|
|
|
|
|
{
|
|
|
|
|
|
return texture;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2025-06-15 20:14:45 +08:00
|
|
|
|
{
|
2025-06-16 00:15:41 +08:00
|
|
|
|
Debug.LogError($"Failed to load image from {fullPath}");
|
|
|
|
|
|
return null;
|
2025-06-15 20:14:45 +08:00
|
|
|
|
}
|
2025-06-16 00:15:41 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
IEnumerator LoadSpriteT(string spName, GameObject go, SpriteRenderer sprite)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (File.Exists(spName))
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] bytes = File.ReadAllBytes(spName);
|
|
|
|
|
|
Texture2D texture = new Texture2D(2, 2); // <20><>ʼ<EFBFBD><CABC>С<EFBFBD><D0A1><EFBFBD>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (texture.LoadImage(bytes)) // <20><><EFBFBD><EFBFBD> JPG <20><> Texture2D
|
|
|
|
|
|
{
|
|
|
|
|
|
sprite.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero, 100f);
|
|
|
|
|
|
Debug.Log($"Loaded {spName} successfully");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError($"Failed to load image from {spName}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError($"File not found: {spName}");
|
|
|
|
|
|
}
|
|
|
|
|
|
yield break;
|
|
|
|
|
|
//using (UnityWebRequest req = UnityWebRequestTexture.GetTexture(spName))
|
|
|
|
|
|
//{
|
|
|
|
|
|
// yield return req.SendWebRequest();
|
|
|
|
|
|
// if (req.result == UnityWebRequest.Result.Success)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Texture2D tt = DownloadHandlerTexture.GetContent(req);
|
|
|
|
|
|
// if (tt == null)
|
|
|
|
|
|
// yield break;
|
|
|
|
|
|
// sprite.sprite = Sprite.Create(tt, new Rect(0, 0, tt.width, tt.height), Vector2.zero, 100f);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// else
|
|
|
|
|
|
// {
|
|
|
|
|
|
// UIWindow.Instance.ShowMessage(req.error);
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-14 13:46:24 +08:00
|
|
|
|
}
|