#include "EntityRes.h"
#include "JudgeHit.h"
#include "MyUtil.h"
#include "lua.hpp"
#include <Quadtree.hpp>

EntityLayer::~EntityLayer()
{
	if (quadTree)
		delete quadTree;
}

GameFunc gameFunc;
/*-----------------------------------------------------------声音-----------------------------------------------------------*/
std::unordered_map<std::wstring, Mix_Chunk*> loadedSound;//已载入的声音
std::unordered_map<std::wstring, EntityDll> loadedEntityDll;
std::unordered_map<std::wstring, std::wstring> soundTable;//音效表
std::unordered_map<int, std::wstring> drumTable;//鼓表
//字体表
std::string pixelFont_size12;
int pixelFont_size12_arg;
std::string pixelFont_size14;
int pixelFont_size14_arg;
std::string highQualityFont;
float msgboxTextOffy;

int LuaFunc_AddSoundTable(lua_State* L)
{
	auto argNum = lua_gettop(L);
	if (argNum != 2)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"AddSoundTable(soundName,soundFile)\n实际收到参数数量为：%d", argNum);
		MessageBoxW(nullptr, err, L"脚本函数AddSoundTable参数数量错误", MB_OK | MB_ICONWARNING);
		exit(0);
	}
	auto src = lua_tostring(L, 1);
	auto dst = lua_tostring(L, 2);
	std::vector<wchar_t> srcbuff, dstbuff;
	UTF8ToUTF16(src, &srcbuff);
	UTF8ToUTF16(dst, &dstbuff);
	auto iter = soundTable.find(srcbuff.data());
	if (iter != soundTable.end())
		soundTable.erase(iter);
	soundTable.insert(std::make_pair(srcbuff.data(), dstbuff.data()));
	return 0;
}

int LuaFunc_AddDrumTable(lua_State* L)
{
	auto argNum = lua_gettop(L);
	if (argNum != 2)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"AddDrumTable(index,drumName)\n实际收到参数数量为：%d", argNum);
		MessageBoxW(nullptr, err, L"脚本函数AddSoundTable参数数量错误", MB_OK | MB_ICONWARNING);
		exit(0);
	}
	auto index = lua_tointeger(L, 1);
	auto drumName = lua_tostring(L, 2);
	std::vector<wchar_t> wbuff;
	UTF8ToUTF16(drumName, &wbuff);
	auto iter = drumTable.find((int)index);
	if (iter != drumTable.end())
		drumTable.erase(iter);
	drumTable.insert(std::make_pair(index, wbuff.data()));
	return 0;
}

int SetPixelFont_Size12(lua_State* L)
{
	auto argNum = lua_gettop(L);
	if (argNum != 2)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"SetPixelFont_Size12(fontName,fontSize)\n实际收到参数数量为：%d", argNum);
		MessageBoxW(nullptr, err, L"脚本函数SetPixelFont_Size12参数数量错误", MB_OK | MB_ICONWARNING);
		exit(0);
	}
	pixelFont_size12 = lua_tostring(L, 1);
	pixelFont_size12_arg = (int)lua_tointeger(L, 2);
	return 0;
}

int SetPixelFont_Size14(lua_State* L)
{
	auto argNum = lua_gettop(L);
	if (argNum != 2)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"SetPixelFont_Size14(fontName,fontSize)\n实际收到参数数量为：%d", argNum);
		MessageBoxW(nullptr, err, L"脚本函数SetPixelFont_Size14参数数量错误", MB_OK | MB_ICONWARNING);
		exit(0);
	}
	pixelFont_size14 = lua_tostring(L, 1);
	pixelFont_size14_arg = (int)lua_tointeger(L, 2);
	return 0;
}

int SetHQFont(lua_State* L)
{
	auto argNum = lua_gettop(L);
	if (argNum != 1)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"SetHQFont(fontName)\n实际收到参数数量为：%d", argNum);
		MessageBoxW(nullptr, err, L"脚本函数SetHQFont参数数量错误", MB_OK | MB_ICONWARNING);
		exit(0);
	}
	highQualityFont = lua_tostring(L, 1);
	return 0;
}

int SetMsgboxTextOffY(lua_State* L)
{
	auto argNum = lua_gettop(L);
	if (argNum != 1)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"SetMsgboxTextOffY(y)\n实际收到参数数量为：%d", argNum);
		MessageBoxW(nullptr, err, L"脚本函数SetMsgboxTextOffY参数数量错误", MB_OK | MB_ICONWARNING);
		exit(0);
	}
	msgboxTextOffy = (float)lua_tonumber(L, 1);
	return 0;
}

const luaL_Reg translateFuncList[] =
{
	{"AddSoundTable", LuaFunc_AddSoundTable},
	{"AddDrumTable", LuaFunc_AddDrumTable},
	{"SetPixelFont_Size12", SetPixelFont_Size12},
	{"SetPixelFont_Size14", SetPixelFont_Size14},
	{"SetHQFont", SetHQFont},
	{"SetMsgboxTextOffY", SetMsgboxTextOffY},
	{NULL, NULL},
};

int InitTranslateLua(lua_State* L)
{
	luaL_newlib(L, translateFuncList);
	return 1;
}

lua_State* NewTranslateLua()
{
	auto L = luaL_newstate();
	luaL_openlibs(L);
	luaL_requiref(L, "mylib", InitTranslateLua, 0);
	std::string cmd;
	char appendStr[MAX_PATH];
	sprintf_s(appendStr, "mylib = require(\"mylib\");\n");
	cmd.append(appendStr);
	for (auto& f : translateFuncList)
		if (f.name != NULL)
		{
			sprintf_s(appendStr, "%s = mylib.%s;\n", f.name, f.name);
			cmd.append(appendStr);
		}
	luaL_dostring(L, cmd.c_str());
	return L;
}
void LoadSoundTable()
{
	auto L = NewTranslateLua();
	std::vector<char> utf8;
	std::vector<wchar_t> wbuff;
	UTF16ToUTF8(L"./data/soundTable.lua", &utf8);
	if (luaL_dofile(L, utf8.data()) != LUA_OK)
	{
		auto err = lua_tostring(L, -1);
		UTF8ToUTF16(err, &wbuff);
		wchar_t title[MAX_PATH];
		swprintf_s(title, L"在%s脚本发生错误", wbuff.data());
		MessageBox(nullptr, wbuff.data(), title, MB_ICONWARNING);
		lua_pop(L, 1);
	}
	lua_close(L);
}
void LoadFontTable()
{
	auto L = NewTranslateLua();
	std::vector<char> utf8;
	std::vector<wchar_t> wbuff;
	UTF16ToUTF8(L"./data/fontTable.lua", &utf8);
	if (luaL_dofile(L, utf8.data()) != LUA_OK)
	{
		auto err = lua_tostring(L, -1);
		UTF8ToUTF16(err, &wbuff);
		wchar_t title[MAX_PATH];
		swprintf_s(title, L"在%s脚本发生错误", wbuff.data());
		MessageBox(nullptr, wbuff.data(), title, MB_ICONWARNING);
		lua_pop(L, 1);
	}
	lua_close(L);
}

Mix_Chunk* GetSoundByName(const wchar_t* soundName)//取需要的声音
{
	auto iter = loadedSound.find(soundName);
	if (iter == loadedSound.end())
	{
		wchar_t wbuff[MAX_PATH];
		swprintf_s(wbuff, L"./data/wav/%s.wav", soundName);
		std::vector<char> utf8;
		UTF16ToUTF8(wbuff, &utf8);
		auto Mix_Chunk = Mix_LoadWAV(utf8.data());
		loadedSound.insert(std::make_pair(soundName, Mix_Chunk));
		return Mix_Chunk;
	}
	return iter->second;
}

bool g_DisableSound = false;

void PlaySound(const wchar_t* soundName)//播放声音
{
	if (g_DisableSound)
		return;
	auto iter = soundTable.find(soundName);
	if (iter != soundTable.end())
	{
		auto soundFileName = iter->second.c_str();
		//播放wav文件
		Mix_PlayChannel(-1, GetSoundByName(soundFileName), 0);
	}
}

int PlayLoopSound(const wchar_t* soundName)
{
	auto iter = soundTable.find(soundName);
	if (iter != soundTable.end())
	{
		auto soundFileName = iter->second.c_str();
		//播放wav文件
		return Mix_PlayChannel(-1, GetSoundByName(soundFileName), -1);
	}
	return -1;
}

void StopLoopSound(int channelID)
{
	Mix_HaltChannel(channelID);
}

/*--------------------------------------------------------------------------------------------------*/
std::unordered_map<MapLayer*, EntityLayer>* EntityRes::GetLoadedEntity(EntityRes* entityRes)
{
	return (std::unordered_map<MapLayer*, EntityLayer>*) & entityRes->loadedEntity;
}

EntityRes::EntityRes()
{
	//语言
	entityLanguage = L"默认";
	gamePid.pEntityLanguage = &entityLanguage;
}

EntityRes::~EntityRes()
{
	Reset();
	if (myfont14)
		TTF_CloseFont(myfont14);
	ClearTexture(&loadedPidTexture);
	//清理着色器
	for (auto& p : loadedVertexShader)
		p.second->Release();
	loadedVertexShader.clear();
	for (auto& p : loadedPixelShader)
		p.second->Release();
	loadedPixelShader.clear();
	//清理预渲染贴图
	pRenderer->ClearBuffer(&preTexture);
}

void EntityRes::Init(MyDX11Renderer* pRenderer, MyView* pView, int* pMapW, int* pMapH)
{
	this->pRenderer = pRenderer;
	this->pView = pView;
    this->pMapW = pMapW;
    this->pMapH = pMapH;
	if (loadedEntityDll.empty())
		LoadEntityDll();
	Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024);
	LoadSoundTable();
	LoadFontTable();
	gameFunc.PlaySound = PlaySound;
	gameFunc.PlayLoopSound = PlayLoopSound;
	gameFunc.StopLoopSound = StopLoopSound;
	gameFunc.GetLoadedEntity = (std::unordered_map<MapLayer*, EntityLayer>*(*)(void* entityRes))EntityRes::GetLoadedEntity;
	gameFunc.entityRes = this;
	gameFunc.GameCreateEntity = EntityRes::GameCreateEntity;
	gameFunc.SetEntity = EntityRes::SetEntity;
	gameFunc.GetDisplayInfo = (void (*)(void*, float*, float*, float*, float*, float*))EntityRes::GetDisplayInfo;
	gameFunc.GetMousePos = (void (*)(void*, float*, float*))EntityRes::GetMousePos;
	gameFunc.InScreen = (bool (*)(void*, float, float))EntityRes::InScreen;
	gameFunc.GridTouch = (void (*)(void*, std::weak_ptr<Entity>, EntityLayer*))EntityRes::GridTouch;
    gameFunc.GetPath = EntityRes::GetPath;
    gameFunc.LineTest = EntityRes::LineTest;
	gameFunc.mapSizeGetter = this;
	gameFunc.GetMapSize = (void(*)(void*, int*, int*))EntityRes::GetMapSize;
	gameFunc.DecodeRecord = DecodeRecord;
	myfont14 = pRenderer->MyLoadFont(pixelFont_size14.c_str(), pixelFont_size14_arg);
}

void EntityRes::Reset()
{
    pfSys.clear();
	loadedEntity.clear();
	for (auto& p : fontMap_myfont14)
	{
		if (p.second.pSRV)
			p.second.pSRV->Release();
		if (p.second.pTexture)
			p.second.pTexture->Release();
	}
	fontMap_myfont14.clear();
}

void EntityRes::RefreshImage()
{
	ClearTexture(&loadedPidTexture);
}

void EntityRes::StepEntityLayer(MyMapLayer* pLayer)
{
	EntityLayer* entityLayer = GetEntityLayer(pLayer);
	StepList(&entityLayer->Ls);
	StepList(&entityLayer->Am);
	StepList(&entityLayer->Pe);
	AmStep(entityLayer);
	//创建实体
	if (!entityLayer->addList.empty())
	{
		for (size_t i = 0; i < entityLayer->addList.size(); i++)
		{
			auto& e = entityLayer->addList.at(i);
			switch (e->type)
			{
			default:
			case 0://实体
				entityLayer->Ls.push_back(e);
				break;
			case 1://玩家
				break;
			case 2://弹药
				entityLayer->Am.push_back(e);
				break;
			case 3://粒子
				entityLayer->Pe.push_back(e);
				break;
			}
			e->mapLayer = pLayer;
			e->entityLayer = entityLayer;
			e->gameFunc = &gameFunc;
			if (!e->initCheck)
				e->Init(e);
		}
		entityLayer->addList.clear();
	}
    //寻路系统
    auto iter = pfSys.find(entityLayer);
    if (iter != pfSys.end())
        iter->second.Step();
}

void EntityRes::StepEntityLayerPe(MyMapLayer* pLayer)
{
	EntityLayer* entityLayer = GetEntityLayer(pLayer);
	StepList(&entityLayer->Pe);
	//创建实体
	if (!entityLayer->addList.empty())
	{
		for (size_t i = 0; i < entityLayer->addList.size(); i++)
		{
			auto& e = entityLayer->addList.at(i);
			switch (e->type)
			{
			default:
			case 0://实体
				entityLayer->Ls.push_back(e);
				break;
			case 1://玩家
				break;
			case 2://弹药
				entityLayer->Am.push_back(e);
				break;
			case 3://粒子
				entityLayer->Pe.push_back(e);
				break;
			}
			e->mapLayer = pLayer;
			e->entityLayer = entityLayer;
			e->gameFunc = &gameFunc;
			if (!e->initCheck)
				e->Init(e);
		}
		entityLayer->addList.clear();
	}
}

void EntityRes::DrawEntityLayer(MyMapLayer* pLayer, bool bApplyMyFar, bool inTopDraw)
{
	EntityLayer* entityLayer = GetEntityLayer(pLayer);
	static std::list<std::shared_ptr<Entity>> Ls2;
	MyView srcView = *pView;
	if (pLayer->layerType == 1)
	{
		float farValue = MyFar(pLayer->myFar);//计算随距离增加，眼睛中物体移动距离
		pView->offX += pLayer->offx;
		pView->offY += pLayer->offy;
		if (bApplyMyFar)
		{
			pView->offX -= (1 - farValue) * pView->offX;
			pView->offY -= (1 - farValue) * pView->offY;
		}
	}
	//绘制最先绘制实体
	for (auto& p : entityLayer->Ls)
	{
		//跳过发光实体
		if (p->light.usingLight)
			continue;
		if (!p->drawBeforeOtherEntity)
			continue;
		if (p->drawAfterPlayer)
			Ls2.push_back(p);
		else
		{
			if (p->shader.usingShader)
				DrawShaderEntity(p, inTopDraw);
			else
				DrawAddEntity(p, inTopDraw);
		}	
	}
	for (auto& p : Ls2)
	{
		//跳过发光实体
		if (p->light.usingLight)
			continue;
		if (!p->drawBeforeOtherEntity)
			continue;
		if (p->shader.usingShader)
			DrawShaderEntity(p, inTopDraw);
		else
			DrawAddEntity(p, inTopDraw);
	}
	DrawEntity();
	Ls2.clear();//Ls2清除
	for (auto& p : entityLayer->Am)
	{
		//跳过发光实体
		if (p->light.usingLight)
			continue;
		if (!p->drawBeforeOtherEntity)
			continue;
		if (p->shader.usingShader)
			DrawShaderEntity(p, inTopDraw);
		else
			DrawAddEntity(p, inTopDraw);
	}
	DrawEntity();
	for (auto& p : entityLayer->Pe)
	{
		//跳过发光实体
		if (p->light.usingLight)
			continue;
		if (!p->drawBeforeOtherEntity)
			continue;
		if (p->shader.usingShader)
			DrawShaderEntity(p, inTopDraw);
		else
			DrawAddEntity(p, inTopDraw);
	}
	DrawEntity();
	//绘制其他实体
	for (auto& p : entityLayer->Ls)
	{
		//跳过发光实体
		if (p->light.usingLight)
			continue;
		if (p->drawBeforeOtherEntity)
			continue;
		if (p->drawAfterPlayer)
			Ls2.push_back(p);
		else
		{
			if (p->shader.usingShader)
				DrawShaderEntity(p, inTopDraw);
			else
				DrawAddEntity(p, inTopDraw);
		}
	}
	for (auto& p : Ls2)
	{
		//跳过发光实体
		if (p->light.usingLight)
			continue;
		if (p->drawBeforeOtherEntity)
			continue;
		if (p->shader.usingShader)
			DrawShaderEntity(p, inTopDraw);
		else
			DrawAddEntity(p, inTopDraw);
	}
	DrawEntity();
	Ls2.clear();//Ls2清除
	for (auto& p : entityLayer->Am)
	{
		//跳过发光实体
		if (p->light.usingLight)
			continue;
		if (p->drawBeforeOtherEntity)
			continue;
		if (p->shader.usingShader)
			DrawShaderEntity(p, inTopDraw);
		else
			DrawAddEntity(p, inTopDraw);
	}
	DrawEntity();
	for (auto& p : entityLayer->Pe)
	{
		//跳过发光实体
		if (p->light.usingLight)
			continue;
		if (p->drawBeforeOtherEntity)
			continue;
		if (p->shader.usingShader)
			DrawShaderEntity(p, inTopDraw);
		else
			DrawAddEntity(p, inTopDraw);
	}
	DrawEntity();
	//绘制文本
	for (auto& p : entityLayer->Ls)
		if (p->el.flag.text)
			DrawEntityText(p, pLayer->color, inTopDraw);
	if (pLayer->layerType == 1)
		*pView = srcView;
}

void EntityRes::DeltaTimeEntityLayer(MyMapLayer* pLayer, float deltaTime)
{
	EntityLayer* entityLayer = GetEntityLayer(pLayer);
	for (auto& we : entityLayer->Ls)
		we->DeltaTime(deltaTime);
	for (auto& we : entityLayer->Am)
		we->DeltaTime(deltaTime);
	for (auto& we : entityLayer->Pe)
		we->DeltaTime(deltaTime);
}

void EntityRes::DrawAddEntity(std::shared_ptr<Entity>& we, bool inTopDraw)
{
	if (we->hide ||
		inTopDraw != (bool)we->topDraw)
		return;
	//通常绘制
	if (we->ani.png[0] != 0 && we->ani.sprite_index[0] != 0)
	{
		auto pidData = gamePid.GetPid(we->ani.png.c_str());
		if (!pidData->aniList.empty())
		{
			auto iter = pidData->aniList.find(we->ani.sprite_index);
			if (iter == pidData->aniList.end())
				return;
			AniPrep* aniPrep = &iter->second;
			if (!aniPrep->layerList.empty() && !aniPrep->layerList.front().frameList.empty())
			{
				MyRect rcScreen;
				rcScreen.Set1(0, 0, pView->window_w, pView->window_h);
				MyRect src, dst;
				for (int index = (int)aniPrep->layerList.size() - 1; index >= 0; index--)
				{
					//是否是隐藏图层号
					if (!we->ani.hideLayerList.empty())
						if (we->ani.hideLayerList.find(index) != we->ani.hideLayerList.end())
							continue;
					auto& aniLayer = aniPrep->layerList.at(index);
					if (we->ani.image_index >= aniLayer.frameList.size())
						we->ani.image_index = 0;
					auto& frame = aniLayer.frameList.at(we->ani.image_index);
					//不绘制0号id
					if (!frame.id)
						continue;
					auto iterFrame = pidData->pidList.find(frame.id);
					if (iterFrame == pidData->pidList.end())
						continue;
					src = pidData->pidList.at(frame.id);
					float xScale = 16.0f / pidData->pid_tile_w;
					float yScale = 16.0f / pidData->pid_tile_h;
					int dx = 0;
					if (we->shock_counter > 0)
						dx = (2 * ((we->shock_counter / 2) % 2) - 1);
					dst.Set1((we->x - 8 + frame.offx + dx) * pView->scale - floorf(pView->offX * pView->scale),
						(we->y - 8 + frame.offy) * pView->scale - floorf(pView->offY * pView->scale),
						src.GetWidth() * pView->scale * xScale,
						src.GetHeight() * pView->scale * yScale);
					//测试绘制区域是否在屏幕内
					if (!rcScreen.IntersectRect(&dst))
						continue;
					GroupByDraw gd;
					gd.src = src;
					gd.dst = dst;
					gd.color = we->color;
					groupByDraw[we->ani.png].push_back(gd);
				}
			}
		}
	}
	//自定义绘制
	if (!we->fillList.empty())
	{
		for (auto& v : we->fillList)
		{
			MyDX11PenVertex vertex;
			vertex.Set(
				(v.x + we->x) * pView->scale - floorf(pView->offX * pView->scale),
				(v.y + we->y) * pView->scale - floorf(pView->offY * pView->scale),
				0,
				v.c);
			fillList.push_back(vertex);
		}
	}
	if (!we->lineList.empty())
	{
		for (auto& v : we->lineList)
		{
			MyDX11PenVertex vertex;
			vertex.Set(
				(v.x + we->x) * pView->scale - floorf(pView->offX * pView->scale),
				(v.y + we->y) * pView->scale - floorf(pView->offY * pView->scale),
				0,
				v.c);
			lineList.push_back(vertex);
		}
	}
}

void EntityRes::DrawShaderEntity(std::shared_ptr<Entity>& we, bool inTopDraw)
{
	//立即绘制之前已添加到绘制列表的实体
	DrawEntity();
	//开始绘制着色器实体
	//绘制到预渲染贴图上
	AniPrep* ap = nullptr;
	if (!(we->hide || inTopDraw != (bool)we->topDraw))
	{
		//通常绘制
		if (we->ani.png[0] != 0 && we->ani.sprite_index[0] != 0)
		{
			auto pidData = gamePid.GetPid(we->ani.png.c_str());
			if (!pidData->aniList.empty())
			{
				auto iter = pidData->aniList.find(we->ani.sprite_index);
				if (iter != pidData->aniList.end())
				{
					ap = &iter->second;
				}
			}
		}
	}
	if (!ap)
		return;
	//保存最后一次用的RTV
	auto lastRTV = pRenderer->GetPenRTV();
	MyView lastView = *pView;
	GetPreTexture((UINT)((ap->texture_left + ap->texture_right) * pView->scale), (UINT)((ap->texture_up + ap->texture_down) * pView->scale));
	pRenderer->SetPenRTV(preTexture.pRTV);
	pRenderer->SetClipVpMVP((ap->texture_left + ap->texture_right) * pView->scale, (ap->texture_up + ap->texture_down) * pView->scale);
	pRenderer->RenderClearRTV(preTexture.pRTV);
	//立即绘制
	float eSrcX = we->x;
	float eSrcY = we->y;
	we->x = (float)ap->texture_left;
	we->y = (float)ap->texture_up;
	pView->offX = 0;
	pView->offY = 0;
	DrawAddEntity(we, inTopDraw);
	DrawEntity();
	//恢复RTV
	pRenderer->ResetClipVpMVP();
	pRenderer->SetPenRTV(lastRTV);
	//恢复view
	*pView = lastView;
	we->x = eSrcX;
	we->y = eSrcY;

	//设置着色器
	if (we->shader.vs.length() > 0)
	{
		auto vs = GetVertexShader(we->shader.vs.c_str());
		if (vs)
			pRenderer->SetTPenVertexShader(vs);
		else
			pRenderer->SetTPenVertexShader();//使用默认着色器
	}
	else
	{
		pRenderer->SetTPenVertexShader();//使用默认着色器
	}
	if (we->shader.ps.length() > 0)
	{
		auto ps = GetPixelShader(we->shader.ps.c_str());
		if (ps)
			pRenderer->SetTPenPixelShader(ps);
		else
			pRenderer->SetTPenPixelShader();//使用默认着色器
	}
	else
	{
		pRenderer->SetTPenPixelShader();//使用默认着色器
	}
	//设置常量缓存
	if (!we->shader.args.empty())
		pRenderer->MapPenConstBuffer2(we->shader.args.data(), (UINT)(we->shader.args.size() * sizeof(float)));
	pRenderer->SetTPenDraw(preTexture.pSRV);
	MyRect src, dst;
	src.Set1(0, 0,
		(ap->texture_left + ap->texture_right) * pView->scale,
		(ap->texture_up + ap->texture_down) * pView->scale);
	dst.Set1((we->draw_x - ap->texture_left) * pView->scale - floorf(pView->offX * pView->scale),
		(we->draw_y - ap->texture_up) * pView->scale - floorf(pView->offY * pView->scale),
		src.right - src.left, src.bottom - src.top);
	//添加绘制区域
	pRenderer->AddRenderCopy(&src, &dst, we->color);
	//立即绘制
	pRenderer->DrawRenderCopy();
	//恢复着色器
	pRenderer->SetTPenVertexShader();
	pRenderer->SetTPenPixelShader();
	//恢复RTV
	pRenderer->SetPenRTV(lastRTV);
}

void EntityRes::DrawEntity()
{
	for (auto& p : groupByDraw)
	{
		auto& drawList = p.second;
		if (drawList.empty())
			continue;
		auto pidData = gamePid.GetPid(p.first.c_str());
		pRenderer->SetTPenDraw(GetPidTexture(p.first.c_str())->pSRV);
		for (auto& t : drawList)
			pRenderer->AddRenderCopy(&t.src, &t.dst, t.color);
		pRenderer->DrawRenderCopy();
		p.second.clear();
	}
	//自定义绘制
	if (!fillList.empty())
	{
		pRenderer->SetPenDraw();
		for (auto& v : fillList)
			pRenderer->AddVertex(&v);
		pRenderer->DrawFillRect();
		fillList.clear();
	}
	if (!lineList.empty())
	{
		pRenderer->SetPenDraw();
		for (auto& v : lineList)
			pRenderer->AddVertex(&v);
		pRenderer->DrawLine();
		lineList.clear();
	}
}

void EntityRes::DrawEntityText(std::weak_ptr<Entity> e, DWORD color, bool inTopDraw)
{
	auto we = e.lock();
	if (!we)
		return;
	if (we->hide ||
		inTopDraw != (bool)we->topDraw)
		return;
	if (!we->el.flag.text)
		return;
	//绘制实体文本
	float nextX = (we->x - 8) * pView->scale - floorf(pView->offX * pView->scale);
	float nextY = (we->y - 8) * pView->scale - floorf(pView->offY * pView->scale);
	pRenderer->DrawText_Unicode(&fontMap_myfont14, myfont14, we->el.eid.c_str(), nextX, &nextX, &nextY, color, pView->scale, true);
}

void EntityRes::DrawEntityCbRectLayer(MyMapLayer* pLayer)
{
	EntityLayer* entityLayer = GetEntityLayer(pLayer);
	MyView srcView = *pView;
	if (pLayer->layerType == 1)
	{
		float farValue = MyFar(pLayer->myFar);//计算随距离增加，眼睛中物体移动距离
		pView->offX += pLayer->offx;
		pView->offY += pLayer->offy;
		pView->offX -= (1 - farValue) * pView->offX;
		pView->offY -= (1 - farValue) * pView->offY;
	}
	pRenderer->SetPenDraw();
	DWORD red = RGBA(0xff, 0, 0, 0xff);
	DWORD green = RGBA(0, 0xff, 0, 0xff);
	DWORD yellow = RGBA(0xff, 0xff, 0, 0xff);
	for (auto& p : entityLayer->Ls)
		DrawAddEntityCbRect(p, green);
	for (auto& p : entityLayer->Am)
	{
		if (!p->attackState)
			continue;
		if (!p->attackParent.expired())
		{
			DWORD c = red;//敌方抛射物用红色
			DrawAddEntityCbRect(p, c);
		}
		else
			DrawAddEntityCbRect(p, red);
	}
	for (auto& p : entityLayer->Pe)
		DrawAddEntityCbRect(p, green);
	pRenderer->DrawLine();
	if (pLayer->layerType == 1)
		*pView = srcView;
}

void EntityRes::EntityInitCheck(std::shared_ptr<Entity>& we)
{
	if (!we->initCheck)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"实体%s[%s][%s]未初始化，\n是否手动初始化？", we->el.name.c_str(), we->ani.png.c_str(), we->ani.sprite_index.c_str());
		if (MessageBox(nullptr, err, L"实体未通过初始化检查", MB_ICONINFORMATION | MB_YESNO) == IDYES)
			we->Init(we);
	}
}

void EntityRes::EntitySharedPtrCheck(std::shared_ptr<Entity>& we)
{
	if (we.use_count() > 1)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"实体%s[%s][%s]在其他地方保存了强引用，数量总共为%d个。\n请修改程序！", we->el.name.c_str(), we->ani.png.c_str(), we->ani.sprite_index.c_str(), we.use_count());
		if (MessageBox(nullptr, err, L"实体未通过强引用数量检查", MB_ICONWARNING | MB_YESNO) == IDYES)
			we->Init(we);
	}
}

void EntityRes::StepList(std::list<std::shared_ptr<Entity>>* entityList)
{
	for (auto& we : *entityList)
	{
		//检查实体有没有被初始化
		EntityInitCheck(we);
		//从四叉树中移除
		GridRemoveEntity(we);
		//清理实体
		if (!we->inUsing)
			continue;
		if (we->hide)
			continue;
		if (we->initCollision)
		{
			we->initCollision = false;
			we->ClearCollisionResult();
			we->Collision();
		}
		we->Step();
		//在四叉树中插入
		GridSetEntity(we);
		//动画
		EntityAniStep(we);
		//死亡事件触发器
		if (we->hp == 0 &&
			we->el.flag.tDeath &&
			we->el.eventName.length() > 0 &&
			we->gameFunc->StartEvent)
		{
			we->gameFunc->StartEvent(we->gameFunc->gameScript, we->el.eventName.c_str(), L"tDeath");
			we->el.flag.tDeath = false;
		}
		if (we->type != 3)
		{
			//如果这个实体是物品
			if (we->isItem)
			{
				//寻找与它接触的实体（在网格中找）
				GridItemTarget(we);
			}
			//破坏了星星砖
			if (we->cbRect.updatedPxmArr && !we->cbRect.updatedPxmArr->empty())
			{
				//编辑器部分无效果
				we->cbRect.updatedPxmArr->clear();
			}
		}
	}
	entityList->remove_if([&](std::shared_ptr<Entity>& we)
	{
		if (!we->inUsing)
		{
			//检查实体有没有被初始化
			EntityInitCheck(we);
			//从四叉树中移除
			GridRemoveEntity(we);
		}
		return !we->inUsing;
	});
}

void EntityRes::GetLoadedEntityDllInfo(std::unordered_map<std::wstring, std::vector<std::wstring>>* infoList)
{
	infoList->clear();
	for (auto& p : loadedEntityDll)
	{
		infoList->insert(std::make_pair(p.first, std::vector<std::wstring>()));
		auto& t = infoList->at(p.first);
		int i_max = p.second._GetEntityCount();
		for (int i = 0; i < i_max; i++)
			t.push_back(p.second._GetEntityName(i));
	}
}

void EntityRes::AmStep(EntityLayer* entityLayer)
{
	for (auto& am : entityLayer->Am)
	{
		//攻击重置计数
		for (auto& target : am->damaged)
		{
			auto& counter = target.second;
			if (counter > 0)
				counter--;
		}
		std::erase_if(am->damaged, [](const auto& item) 
		{
			return item.second == 0;
		});
		//实体Am
		if (GridAmTarget(am))
			continue;//到达攻击次数上限
	}
}

bool EntityRes::AmTarget(std::shared_ptr<Entity>& am, std::shared_ptr<Entity>& target)
{
	//跳过自身
	if (am == target)
		return false;
	if (!am->attackState)
		return false;
	//攻击次数上限（下帧前退出该抛射物所有的执行）
	if (am->damaged_limit != 0 && am->damaged_counter >= am->damaged_limit)
		return true;

	int damage = 0;
	float angle = 0;
	bool bTakedown = false;
	int elemType = 0;
	float shockForce = 0;
	float heavy = 0;
	int realDamage = 0;
	bool trapAttack = am->isTrap && !target->isTrap && !target->ignoreTrap && target->ignoreTrap_counter == 0;
	if (!trapAttack)
	{
		int amType = am->type;
		auto wam_attackParent = am->attackParent.lock();
		if (wam_attackParent)
			amType = wam_attackParent->type;
		int targetType = target->type;
		auto wtarget_attackParent = target->attackParent.lock();
		if (targetType == 2 && wtarget_attackParent)
			targetType = wtarget_attackParent->type;
		//相同阵营不会攻击
		if (amType == targetType)
			return false;
		//不会攻击自己发射的物体
		if (am == wtarget_attackParent)
			return false;
	}
	//检查目标是否已被攻击过
	if (am->damaged.find(target.get()) != am->damaged.end())
		return false;
	//瞬杀情况计算（会耗尽所有攻击次数在这次攻击上面）
	bool bHurt = false;
	do
	{
		//调用Attack
		am->Attack(target, &damage, &angle, &bTakedown, &elemType, &shockForce, &heavy);
		//调用Hurt
		if (target->inUsing && target->Hurt(am, damage, angle, bTakedown, elemType, shockForce, heavy, &realDamage))
		{
			bHurt = true;
			//攻击次数累计
			am->damaged_counter++;
		}
		else
		{
			break;
		}
	} while (am->damage_reset_counter == 0 &&
		am->damaged_counter < am->damaged_limit);
	if (bHurt)
	{
		MyRect src, dst;
		SDL_FRect sdlSrc, sdlDst, intersectRect;
		src.Set2(am->x - (am->cbRect.left),
			am->x + (am->cbRect.right),
			am->y - (am->cbRect.top),
			am->y + (am->cbRect.bottom));
		dst.Set2(target->x - target->cbRect.left,
			target->x + target->cbRect.right,
			target->y - target->cbRect.top,
			target->y + target->cbRect.bottom);
		sdlSrc.x = src.left;
		sdlSrc.w = src.right - src.left;
		sdlSrc.y = src.top;
		sdlSrc.h = src.bottom - src.top;
		sdlDst.x = dst.left;
		sdlDst.w = dst.right - dst.left;
		sdlDst.y = dst.top;
		sdlDst.h = dst.bottom - dst.top;
		//添加到攻击忽略表
		am->AddDamagedEntity(target.get());
		//计算相交矩形
		SDL_IntersectFRect(&sdlSrc, &sdlDst, &intersectRect);
		//取相交矩形中点坐标（产生效果物体）
		am->AttackEffectObject(target, intersectRect.x + intersectRect.w / 2.0f, intersectRect.y + intersectRect.h / 2.0f, realDamage);
		//调用攻击反馈feedback
		am->Feedback(target);
	}
	return false;
}

static const bool PxaIsEmptyTable[] =
{
	true ,true ,false,false,false,false,false,false,false,false,false,false,false,false,false,true ,
	true ,true ,false,false,false,false,false,false,false,false,false,false,false,false,false,true ,
	true ,true ,false,false,false,false,false,false,false,false,false,false,false,false,false,true ,
	true ,true ,false,false,false,false,false,false,false,false,false,false,false,false,false,true ,
	true ,true ,true ,false,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,
	true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,
	true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,
	true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,
};

bool PxaIsEmpty(int pxaID)
{
	return PxaIsEmptyTable[pxaID];
}

static const int WaterBlockTable[] =
{
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xff,0x02,0xff,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0x02,0xff,0xff,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xff,0x02,0x02,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
};

int WaterBlock(int pxaID)
{
	return WaterBlockTable[pxaID] == 0xff ? pxaID : WaterBlockTable[pxaID];
}

int IndexLRTBPxa(int X, int Y, std::unordered_map<LONG, LONG>& pxmData, std::unordered_map<LONG, int>& pxaData)
{
	int pxa = 0;
	auto iter_pxa_pxmData = pxmData.find(MAKELONG(X, Y));
	if (iter_pxa_pxmData != pxmData.end())
	{
		auto iter_pxa_pxaData = pxaData.find(iter_pxa_pxmData->second);
		if (iter_pxa_pxaData != pxaData.end())
			pxa = iter_pxa_pxaData->second;
	}
	return pxa;
}

void EntityRes::CollisionEntity(std::weak_ptr<Entity> e, std::vector<LONG>* pxmArr, std::vector<int>* pxaArr, std::map<LONG, LONG>* updatedPxmArr, int pxmArr_w, int pxaArr_w)
{
	auto we = e.lock();
	if (we)
	{
		EntityRes* _this = (EntityRes*)we->gameFunc->entityRes;
		_this->CollisionMovingPlatform(e);
		if (we->cbRect.left + we->cbRect.right <= 4 ||
			we->cbRect.top + we->cbRect.bottom <= 4)
			CollisionEntitySmall(e, pxmArr, pxaArr, updatedPxmArr, pxmArr_w, pxaArr_w);
		else
			CollisionEntityBig(e, pxmArr, pxaArr, updatedPxmArr, pxmArr_w, pxaArr_w);
	}
}

void EntityRes::CollisionEntityBig(std::weak_ptr<Entity> e, std::vector<LONG>* pxmArr, std::vector<int>* pxaArr, std::map<LONG, LONG>* updatedPxmArr, int pxmArr_w, int pxaArr_w)
{
	auto we = e.lock();
	if (!we)
		return;
	if (!we->cbRect.enableCbRect)//如果不启用碰撞
		return;
	int X_begin = (int)((we->x - we->cbRect.left) / 16.0f);
	int X_end = (int)((we->x + we->cbRect.right) / 16.0f);
	int Y_begin = (int)((we->y - we->cbRect.top) / 16.0f);
	int Y_end = (int)((we->y + we->cbRect.bottom) / 16.0f);
	int X_center = (int)((we->x + (we->cbRect.right - we->cbRect.left) / 2.0f) / 16.0f);
	int Y_center = (int)((we->y + (we->cbRect.bottom - we->cbRect.top) / 2.0f) / 16.0f);

	int offset_tileset = 8;
	int pxm = 0, pxa = 0, pxaL = 0, pxaR = 0, pxaB = 0, pxaT = 0;
	float spikeDamage = 0;
	std::vector<LONG>& pxmData = *pxmArr;
	std::vector<int>& pxaData = *pxaArr;
	int pxmArr_h = (int)pxmData.size() / pxmArr_w;
	bool breakStarBlock = false;
	for (int Y = Y_begin - 1; Y <= Y_end + 1; Y++)
	{
		for (int X = X_begin - 1; X <= X_end + 1; X++)
		{
			if (Y < 0 || X < 0)
				continue;
			pxa = GetSafePxa(X, Y, pxmData, pxaData, pxmArr_w, pxmArr_h);
			pxaL = GetSafePxa(X - 1, Y, pxmData, pxaData, pxmArr_w, pxmArr_h);
			pxaR = GetSafePxa(X + 1, Y, pxmData, pxaData, pxmArr_w, pxmArr_h);
			pxaT = GetSafePxa(X, Y - 1, pxmData, pxaData, pxmArr_w, pxmArr_h);
			pxaB = GetSafePxa(X, Y + 1, pxmData, pxaData, pxmArr_w, pxmArr_h);
			//碰撞
			if (we->cbRect.waterBlock)
			{
				pxa = WaterBlock(pxa);
				pxaL = WaterBlock(pxaL);
				pxaR = WaterBlock(pxaR);
				pxaT = WaterBlock(pxaT);
				pxaB = WaterBlock(pxaB);
			}
			//特殊功能地形
			switch (pxa)
			{
			case 0x1f://只阻挡NPC(水中)
				if (we->type == 0)
					pxa = 0x2;
				else
					JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
				break;
			case 0xf://只阻挡NPC
				if (we->type == 0 || we->type == 2)
					pxa = 0x2;
				break;
			case 0x30://只阻挡玩家（水中）
				if (we->type == 1)
					pxa = 0x2;
				else
					JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
				break;
			case 0x20://只阻挡玩家
				if (we->type == 1)
					pxa = 0x2;
				break;
			case 0x3f://只阻挡AM（水中）
				if (we->type == 2)
					pxa = 0x2;
				else
					JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
				break;
			case 0x2f:
				if (we->type == 2)
					pxa = 0x2;
				break;
			case 0x43://破坏星星砖
				if (!breakStarBlock)
				{
					if (JH_BreakStarBlock(we, X, Y, offset_tileset, pxmData, *updatedPxmArr, pxmArr_w))
						breakStarBlock = true;
				}
				break;
			}
			//通常地形
			switch (pxa)
			{
			case 0x11://水
			case 0x40://背景水
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
				break;
			case 0x41://尖刺5
				JH_InSpike(we, X, Y, offset_tileset, 5);
				break;
			case 0x42://尖刺10
				JH_InSpike(we, X, Y, offset_tileset, 10);
				break;
			case 0x51://水中刺5
				JH_InSpike(we, X, Y, offset_tileset, 5);
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
				break;
			case 0x52://水中刺10
				JH_InSpike(we, X, Y, offset_tileset, 10);
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
				break;
			case 0x53://岩浆
				JH_InLava(we, X, Y, offset_tileset);
				break;
			case 0x2://固体
			case 0x12://浸水固体
			case 0x22://冰固体
			case 0x32://冰浸水固体
			case 0x43://星星砖
				if (X >= X_center)
				{
					switch (pxaL)
					{
					case 0x6:
					case 0x16:
					case 0x26:
					case 0x36:

					case 0xa:
					case 0x1a:
					case 0x2a:
					case 0x3a:

					case 0xc:
					case 0x1c:
					case 0x2c:
					case 0x3c:

					case 0xe:
					case 0x1e:
					case 0x2e:
					case 0x3e:
						break;
					default:
						JH2_JudgeHitMyCharBlock_R(we, X, Y, offset_tileset, pxa);
						break;
					}
				}
				if (X <= X_center)
				{
					switch (pxaR)
					{
					case 0x3:
					case 0x13:
					case 0x23:
					case 0x33:

					case 0x7:
					case 0x17:
					case 0x27:
					case 0x37:

					case 0xb:
					case 0x1b:
					case 0x2b:
					case 0x3b:

					case 0xd:
					case 0x1d:
					case 0x2d:
					case 0x3d:
						break;
					default:
						JH2_JudgeHitMyCharBlock_L(we, X, Y, offset_tileset, pxa);
						break;
					}
				}
				if (Y >= Y_center)
					JH2_JudgeHitMyCharBlock_D(we, X, Y, offset_tileset, pxa);
				if (Y <= Y_center)
					JH2_JudgeHitMyCharBlock_T(we, X, Y, offset_tileset, pxa);
				break;
			case 0x13://水斜坡A
			case 0x33://冰水斜坡A
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x3://斜坡A
			case 0x23://冰斜坡A
				JH2_JudgeHitMyCharTriangleA(we, X, Y, offset_tileset, pxa);
				break;
			case 0x14://水斜坡B
			case 0x34://冰水斜坡B
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x4://斜坡B
			case 0x24://冰斜坡B
				JH2_JudgeHitMyCharTriangleB(we, X, Y, offset_tileset, pxa);
				break;
			case 0x15://水斜坡C
			case 0x35://冰水斜坡C
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x5://斜坡C
			case 0x25://冰斜坡C
				JH2_JudgeHitMyCharTriangleC(we, X, Y, offset_tileset, pxa);
				break;
			case 0x16://水斜坡D
			case 0x36://冰水斜坡D
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x6://斜坡D
			case 0x26://冰斜坡D
				JH2_JudgeHitMyCharTriangleD(we, X, Y, offset_tileset, pxa);
				break;
			case 0x17://水斜坡E
			case 0x37://冰水斜坡E
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x7://斜坡E
			case 0x27://冰斜坡E
				JH2_JudgeHitMyCharTriangleE(we, X, Y, offset_tileset, pxa);
				break;
			case 0x18://水斜坡F
			case 0x38://冰水斜坡F
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x8://斜坡F
			case 0x28://冰斜坡F
				JH2_JudgeHitMyCharTriangleF(we, X, Y, offset_tileset, pxa);
				break;
			case 0x19://水斜坡G
			case 0x39://冰水斜坡G
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x9://斜坡G
			case 0x29://冰斜坡G
				JH2_JudgeHitMyCharTriangleG(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1a://水斜坡H
			case 0x3a://冰水斜坡H
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0xa://斜坡H
			case 0x2a://冰斜坡H
				JH2_JudgeHitMyCharTriangleH(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1b://水斜坡I
			case 0x3b://冰水斜坡I
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0xb://斜坡I
			case 0x2b://冰斜坡I
				JH2_JudgeHitMyCharTriangleI(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1c://水斜坡J
			case 0x3c://冰水斜坡J
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0xc://斜坡J
			case 0x2c://冰斜坡J
				JH2_JudgeHitMyCharTriangleJ(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1d://水斜坡K
			case 0x3d://冰水斜坡K
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0xd://斜坡K
			case 0x2d://冰斜坡K
				JH2_JudgeHitMyCharTriangleK(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1e://水斜坡L
			case 0x3e://冰水斜坡L
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0xe://斜坡L
			case 0x2e://冰斜坡L
				JH2_JudgeHitMyCharTriangleL(we, X, Y, offset_tileset, pxa);
				break;
				/*--------------------------风场------------------------------*/
			case 0x70://左激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x60://左风
				JH_JudgeHitMyCharVectL(we, X, Y, offset_tileset);
				break;
			case 0x71://左上激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x61://左上风
				JH_JudgeHitMyCharVectLU(we, X, Y, offset_tileset);
				break;
			case 0x72://上激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x62://上风
				JH_JudgeHitMyCharVectU(we, X, Y, offset_tileset);
				break;
			case 0x73://右上激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x63://右上风
				JH_JudgeHitMyCharVectRU(we, X, Y, offset_tileset);
				break;
			case 0x74://右激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x64://右风
				JH_JudgeHitMyCharVectR(we, X, Y, offset_tileset);
				break;
			case 0x75://左下激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x65://左下风
				JH_JudgeHitMyCharVectLD(we, X, Y, offset_tileset);
				break;
			case 0x76://下激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x66://下风
				JH_JudgeHitMyCharVectD(we, X, Y, offset_tileset);
				break;
			case 0x77://右下激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x67://右下风
				JH_JudgeHitMyCharVectRD(we, X, Y, offset_tileset);
				break;
			}
		}
	}
	CoyoteTime(we);
}

void EntityRes::CollisionEntitySmall(std::weak_ptr<Entity> e, std::vector<LONG>* pxmArr, std::vector<int>* pxaArr, std::map<LONG, LONG>* updatedPxmArr, int pxmArr_w, int pxaArr_w)
{
	auto we = e.lock();
	if (!we)
		return;
	if (!we->cbRect.enableCbRect)//如果不启用碰撞
		return;
	int X_begin = (int)((we->x - we->cbRect.left) / 16.0f);
	int X_end = (int)((we->x + we->cbRect.right) / 16.0f);
	int Y_begin = (int)((we->y - we->cbRect.top) / 16.0f);
	int Y_end = (int)((we->y + we->cbRect.bottom) / 16.0f);
	int X_center = (int)((we->x + (we->cbRect.right - we->cbRect.left) / 2.0f) / 16.0f);
	int Y_center = (int)((we->y + (we->cbRect.bottom - we->cbRect.top) / 2.0f) / 16.0f);

	int offset_tileset = 8;
	int pxm = 0, pxa = 0, pxaL = 0, pxaR = 0, pxaB = 0, pxaT = 0;
	float spikeDamage = 0;
	we->cbRect.pxaLeft = we->cbRect.pxaRight = we->cbRect.pxaTop = we->cbRect.pxaBottom = 0;
	std::vector<LONG>& pxmData = *pxmArr;
	std::vector<int>& pxaData = *pxaArr;
	int pxmArr_h = (int)pxmData.size() / pxmArr_w;
	bool breakStarBlock = false;
	for (int Y = Y_begin - 1; Y <= Y_end + 1; Y++)
	{
		for (int X = X_begin - 1; X <= X_end + 1; X++)
		{
			if (Y < 0 || X < 0)
				continue;
			pxa = GetSafePxa(X, Y, pxmData, pxaData, pxmArr_w, pxmArr_h);
			pxaL = GetSafePxa(X - 1, Y, pxmData, pxaData, pxmArr_w, pxmArr_h);
			pxaR = GetSafePxa(X + 1, Y, pxmData, pxaData, pxmArr_w, pxmArr_h);
			pxaT = GetSafePxa(X, Y - 1, pxmData, pxaData, pxmArr_w, pxmArr_h);
			pxaB = GetSafePxa(X, Y + 1, pxmData, pxaData, pxmArr_w, pxmArr_h);
			//碰撞
			if (we->cbRect.waterBlock)
			{
				pxa = WaterBlock(pxa);
				pxaL = WaterBlock(pxaL);
				pxaR = WaterBlock(pxaR);
				pxaT = WaterBlock(pxaT);
				pxaB = WaterBlock(pxaB);
			}
			//特殊功能地形
			switch (pxa)
			{
			case 0x1f://只阻挡NPC(水中)
				if (we->type == 0)
					pxa = 0x2;
				else
					JH_InWater(we, X, Y, offset_tileset);
				break;
			case 0xf://只阻挡NPC
				if (we->type == 0 || we->type == 2)
					pxa = 0x2;
				break;
			case 0x30://只阻挡玩家（水中）
				if (we->type == 1)
					pxa = 0x2;
				else
					JH_InWater(we, X, Y, offset_tileset);
				break;
			case 0x20://只阻挡玩家
				if (we->type == 1)
					pxa = 0x2;
				break;
			case 0x3f://只阻挡AM（水中）
				if (we->type == 2)
					pxa = 0x2;
				else
					JH_InWater(we, X, Y, offset_tileset);
				break;
			case 0x2f:
				if (we->type == 2)
					pxa = 0x2;
				break;
			case 0x43://破坏星星砖
				if (!breakStarBlock)
				{
					if (JH_BreakStarBlock(we, X, Y, offset_tileset, pxmData, *updatedPxmArr, pxmArr_w))
						breakStarBlock = true;
				}
				break;
			}
			//通常地形
			switch (pxa)
			{
			case 0x11://水
			case 0x40://背景水
				JH_InWater(we, X, Y, offset_tileset);
				break;
			case 0x41://尖刺5
				JH_InSpike(we, X, Y, offset_tileset, 5);
				break;
			case 0x42://尖刺10
				JH_InSpike(we, X, Y, offset_tileset, 10);
				break;
			case 0x51://水中刺5
				JH_InSpike(we, X, Y, offset_tileset, 5);
				JH_InWater(we, X, Y, offset_tileset);
				break;
			case 0x52://水中刺10
				JH_InSpike(we, X, Y, offset_tileset, 10);
				JH_InWater(we, X, Y, offset_tileset);
				break;
			case 0x53://岩浆
				JH_InLava(we, X, Y, offset_tileset);
				break;
			case 0x2://固体
			case 0x12://浸水固体
			case 0x22://冰固体
			case 0x32://冰浸水固体
			case 0x43://星星砖
				if (X >= X_center)
				{
					switch (pxaL)
					{
					case 0x6:
					case 0x16:
					case 0x26:
					case 0x36:

					case 0xa:
					case 0x1a:
					case 0x2a:
					case 0x3a:

					case 0xc:
					case 0x1c:
					case 0x2c:
					case 0x3c:

					case 0xe:
					case 0x1e:
					case 0x2e:
					case 0x3e:
						break;
					default:
						JH_BlockRight(we, X, Y, offset_tileset, pxa);
						break;
					}
				}
				if (X <= X_center)
				{
					switch (pxaR)
					{
					case 0x3:
					case 0x13:
					case 0x23:
					case 0x33:

					case 0x7:
					case 0x17:
					case 0x27:
					case 0x37:

					case 0xb:
					case 0x1b:
					case 0x2b:
					case 0x3b:

					case 0xd:
					case 0x1d:
					case 0x2d:
					case 0x3d:
						break;
					default:
						JH_BlockLeft(we, X, Y, offset_tileset, pxa);
						break;
					}
				}
				if (Y >= Y_center &&
					((we->cbRect.waterBlock) ||
						(!we->cbRect.waterBlock && PxaIsEmpty(pxaT))))//顶部如果是空的
				{
					switch (pxaL)
					{
					case 0xa:
					case 0x1a:
					case 0x2a:
					case 0x3a:
					case 0xe:
					case 0x1e:
					case 0x2e:
					case 0x3e:
						JH_BlockPointLB(we, X, Y, offset_tileset, pxa);
						break;
					default:
						JH_BlockLB(we, X, Y, offset_tileset, pxa);
						break;
					}
					switch (pxaR)
					{
					case 0x7:
					case 0x17:
					case 0x27:
					case 0x37:
					case 0xd:
					case 0x1d:
					case 0x2d:
					case 0x3d:
						JH_BlockPointRB(we, X, Y, offset_tileset, pxa);
						break;
					default:
						JH_BlockRB(we, X, Y, offset_tileset, pxa);
						break;
					}
				}
				if (Y <= Y_center &&
					((we->cbRect.waterBlock) ||
						(!we->cbRect.waterBlock && PxaIsEmpty(pxaB))))//底部如果是空的
				{
					switch (pxaL)
					{
					case 0x6:
					case 0x16:
					case 0x26:
					case 0x36:
					case 0xc:
					case 0x1c:
					case 0x2c:
					case 0x3c:
						JH_BlockPointLT(we, X, Y, offset_tileset, pxa);
						break;
					default:
						JH_BlockLT(we, X, Y, offset_tileset, pxa);
						break;
					}
					switch (pxaR)
					{
					case 0x3:
					case 0x13:
					case 0x23:
					case 0x33:
					case 0xb:
					case 0x1b:
					case 0x2b:
					case 0x3b:
						JH_BlockPointRT(we, X, Y, offset_tileset, pxa);
						break;
					default:
						JH_BlockRT(we, X, Y, offset_tileset, pxa);
						break;
					}
				}
				break;
			case 0x13://水斜坡A
			case 0x33://冰水斜坡A
				JH_InWater(we, X, Y, offset_tileset);
			case 0x3://斜坡A
			case 0x23://冰斜坡A
				JH_SlopeA(we, X, Y, offset_tileset, pxa);
				break;
			case 0x14://水斜坡B
			case 0x34://冰水斜坡B
				JH_InWater(we, X, Y, offset_tileset);
			case 0x4://斜坡B
			case 0x24://冰斜坡B
				JH_SlopeB(we, X, Y, offset_tileset, pxa);
				break;
			case 0x15://水斜坡C
			case 0x35://冰水斜坡C
				JH_InWater(we, X, Y, offset_tileset);
			case 0x5://斜坡C
			case 0x25://冰斜坡C
				JH_SlopeC(we, X, Y, offset_tileset, pxa);
				break;
			case 0x16://水斜坡D
			case 0x36://冰水斜坡D
				JH_InWater(we, X, Y, offset_tileset);
			case 0x6://斜坡D
			case 0x26://冰斜坡D
				JH_SlopeD(we, X, Y, offset_tileset, pxa);
				break;
			case 0x17://水斜坡E
			case 0x37://冰水斜坡E
				JH_InWater(we, X, Y, offset_tileset);
			case 0x7://斜坡E
			case 0x27://冰斜坡E
				JH_SlopeE(we, X, Y, offset_tileset, pxa);
				break;
			case 0x18://水斜坡F
			case 0x38://冰水斜坡F
				JH_InWater(we, X, Y, offset_tileset);
			case 0x8://斜坡F
			case 0x28://冰斜坡F
				JH_SlopeF(we, X, Y, offset_tileset, pxa);
				break;
			case 0x19://水斜坡G
			case 0x39://冰水斜坡G
				JH_InWater(we, X, Y, offset_tileset);
			case 0x9://斜坡G
			case 0x29://冰斜坡G
				JH_SlopeG(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1a://水斜坡H
			case 0x3a://冰水斜坡H
				JH_InWater(we, X, Y, offset_tileset);
			case 0xa://斜坡H
			case 0x2a://冰斜坡H
				JH_SlopeH(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1b://水斜坡I
			case 0x3b://冰水斜坡I
				JH_InWater(we, X, Y, offset_tileset);
			case 0xb://斜坡I
			case 0x2b://冰斜坡I
				JH_SlopeI(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1c://水斜坡J
			case 0x3c://冰水斜坡J
				JH_InWater(we, X, Y, offset_tileset);
			case 0xc://斜坡J
			case 0x2c://冰斜坡J
				JH_SlopeJ(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1d://水斜坡K
			case 0x3d://冰水斜坡K
				JH_InWater(we, X, Y, offset_tileset);
			case 0xd://斜坡K
			case 0x2d://冰斜坡K
				JH_SlopeK(we, X, Y, offset_tileset, pxa);
				break;
			case 0x1e://水斜坡L
			case 0x3e://冰水斜坡L
				JH_InWater(we, X, Y, offset_tileset);
			case 0xe://斜坡L
			case 0x2e://冰斜坡L
				JH_SlopeL(we, X, Y, offset_tileset, pxa);
				break;
				/*--------------------------风场------------------------------*/
			case 0x70://左激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x60://左风
				JH_JudgeHitMyCharVectL(we, X, Y, offset_tileset);
				break;
			case 0x71://左上激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x61://左上风
				JH_JudgeHitMyCharVectLU(we, X, Y, offset_tileset);
				break;
			case 0x72://上激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x62://上风
				JH_JudgeHitMyCharVectU(we, X, Y, offset_tileset);
				break;
			case 0x73://右上激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x63://右上风
				JH_JudgeHitMyCharVectRU(we, X, Y, offset_tileset);
				break;
			case 0x74://右激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x64://右风
				JH_JudgeHitMyCharVectR(we, X, Y, offset_tileset);
				break;
			case 0x75://左下激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x65://左下风
				JH_JudgeHitMyCharVectLD(we, X, Y, offset_tileset);
				break;
			case 0x76://下激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x66://下风
				JH_JudgeHitMyCharVectD(we, X, Y, offset_tileset);
				break;
			case 0x77://右下激流
				JH2_JudgeHitMyCharWater(we, X, Y, offset_tileset);
			case 0x67://右下风
				JH_JudgeHitMyCharVectRD(we, X, Y, offset_tileset);
				break;
			}
		}
	}
	CoyoteTime(we);
}

void EntityRes::CollisionMovingPlatform(std::weak_ptr<Entity> e)
{
	auto we = e.lock();
	if (!we)
		return;
	if (we->cbRect.ignoreMovePlatform)
		return;
	SDL_FRect qtRect;
	qtRect.x = we->x - we->cbRect.left;
	qtRect.y = we->y - we->cbRect.top;
	qtRect.w = we->cbRect.left + we->cbRect.right;
	qtRect.h = we->cbRect.top + we->cbRect.bottom;
	//使用和地图的相交矩形
	SDL_FRect sdlSrc, intersectRect;
	sdlSrc.x = 0;
	sdlSrc.y = 0;
	sdlSrc.w = *pMapW * 16.0f;
	sdlSrc.h = *pMapH * 16.0f;
	//计算相交矩形
	if (SDL_IntersectFRect(&sdlSrc, &qtRect, &intersectRect) == SDL_TRUE)
	{
		static std::vector<Entity*> quadTreeRes;
		quadTreeRes.clear();
		we->entityLayer->quadTree->query((Rect<float>&)intersectRect, quadTreeRes);
		for (auto& e : quadTreeRes)
		{
			auto wdst = e->self.lock();
			if (wdst)
			{
				//跳过自己
				if (wdst == we)
					continue;
				//含水实体
				we->cbRect.inWater |= wdst->cbRect.enableWaterSpace;
				//被空中平台挤开
				if (wdst->cbRect.enableMovePlatform ||
					(we->type == 1 && wdst->cbRect.enableSelfSoild))
				{
					JH_NPC_BlockL(wdst, we);
					JH_NPC_BlockR(wdst, we);
					JH_NPC_BlockT(wdst, we);
					JH_NPC_BlockB(wdst, we);
				}
			}
		}
	}
}

void EntityRes::SetEntity(std::shared_ptr<Entity> parent, std::shared_ptr<Entity> newE)
{
	newE->gameFunc = parent->gameFunc;
	newE->entityLayer = parent->entityLayer;
	newE->cbRect.roomColor = parent->cbRect.roomColor;
	newE->cbRect.pxmArr = parent->cbRect.pxmArr;
	newE->cbRect.pxaArr = parent->cbRect.pxaArr;
	newE->cbRect.updatedPxmArr = parent->cbRect.updatedPxmArr;
	newE->cbRect.pxmArr_w = parent->cbRect.pxmArr_w;
	newE->cbRect.pxaArr_w = parent->cbRect.pxaArr_w;
	newE->cbRect.Collision = parent->cbRect.Collision;
	EntityLayer* entityLayer = (EntityLayer*)parent->entityLayer;
	if (entityLayer)
		entityLayer->addList.push_back(newE);
}

void EntityRes::SetCollisionEntityLayer(MyMapLayer* pLayer, PxaData* pxaData)
{
	EntityLayer* entityLayer = GetEntityLayer(pLayer);
	for (auto e : entityLayer->Ls)
	{
		e->cbRect.roomColor = pLayer->color;
		e->cbRect.pxmArr = &pLayer->pxmArr;
		e->cbRect.pxaArr = &pxaData->pxaArr;
		e->cbRect.updatedPxmArr = &pLayer->updatedPxmArr;
		e->cbRect.pxmArr_w = pLayer->pxmArr_w;
		e->cbRect.pxaArr_w = pxaData->pxaArr_w;
		e->cbRect.Collision = CollisionEntity;
	}
	for (auto e : entityLayer->Am)
	{
		e->cbRect.roomColor = pLayer->color;
		e->cbRect.pxmArr = &pLayer->pxmArr;
		e->cbRect.pxaArr = &pxaData->pxaArr;
		e->cbRect.updatedPxmArr = &pLayer->updatedPxmArr;
		e->cbRect.pxmArr_w = pLayer->pxmArr_w;
		e->cbRect.pxaArr_w = pxaData->pxaArr_w;
		e->cbRect.Collision = CollisionEntity;
	}
	for (auto e : entityLayer->Pe)
	{
		e->cbRect.roomColor = pLayer->color;
		e->cbRect.pxmArr = &pLayer->pxmArr;
		e->cbRect.pxaArr = &pxaData->pxaArr;
		e->cbRect.updatedPxmArr = &pLayer->updatedPxmArr;
		e->cbRect.pxmArr_w = pLayer->pxmArr_w;
		e->cbRect.pxaArr_w = pxaData->pxaArr_w;
		e->cbRect.Collision = CollisionEntity;
	}
}

void EntityRes::ReloadLanguage()
{
	ClearTexture(&loadedPidTexture);
	gamePid.ReloadLanguage();
	for (auto& p : loadedEntity)
	{
		auto& entityLayer = p.second;
		for (auto& e : entityLayer.Ls)
			e->ReloadLanguage();
		for (auto& e : entityLayer.Am)
			e->ReloadLanguage();
		for (auto& e : entityLayer.Pe)
			e->ReloadLanguage();
	}
}

CString EntityRes::GetErrorMsg()
{
	return err;
}


ID3D11VertexShader* EntityRes::GetVertexShader(const wchar_t* vsName)
{
	auto iter = loadedVertexShader.find(vsName);
	if (iter == loadedVertexShader.end())
	{
		ID3D11VertexShader* vs = nullptr;
		ID3DBlob* blob = nullptr;
		wchar_t wbuff[MAX_PATH];
		swprintf_s(wbuff, L"./data/shader/%s.hlsl", vsName);
		std::vector<char> utf8;
		UTF16ToUTF8(wbuff, &utf8);
		pRenderer->MyCreateVertexShader(&vs, utf8.data(), "VSMain", &blob);
		if (blob)
			blob->Release();
		if (!vs)
			return nullptr;
		loadedVertexShader.insert(std::make_pair(vsName, vs));
		return vs;
	}
	return iter->second;
}

ID3D11PixelShader* EntityRes::GetPixelShader(const wchar_t* psName)
{
	auto iter = loadedPixelShader.find(psName);
	if (iter == loadedPixelShader.end())
	{
		ID3D11PixelShader* ps = nullptr;
		ID3DBlob* blob = nullptr;
		wchar_t wbuff[MAX_PATH];
		swprintf_s(wbuff, L"./data/shader/%s.hlsl", psName);
		std::vector<char> utf8;
		UTF16ToUTF8(wbuff, &utf8);
		pRenderer->MyCreatePixelShader(&ps, utf8.data(), "PSMain", &blob);
		if (blob)
			blob->Release();
		if (!ps)
			return nullptr;
		loadedPixelShader.insert(std::make_pair(psName, ps));
		return ps;
	}
	return iter->second;
}

void EntityRes::GetDisplayInfo(EntityRes* pEntityRes, float* outWindow_w, float* outWindow_h, float* outScale, float* outOffX, float* outOffY)
{
	auto& v = *pEntityRes->pView;
	if (outWindow_w)
		*outWindow_w = v.window_w;
	if (outWindow_h)
		*outWindow_h = v.window_h;
	if (outScale)
		*outScale = v.scale;
	if (outOffX)
		*outOffX = v.offX;
	if (outOffY)
		*outOffY = v.offY;
}

void EntityRes::GetMousePos(EntityRes* pEntityRes, float* pX, float* pY)
{
	auto& v = *pEntityRes->pView;
	int mouseX, mouseY;
	SDL_GetMouseState(&mouseX, &mouseY);
	*pX = (mouseX + floorf(v.offX * v.scale)) / v.scale;
	*pY = (mouseY + floorf(v.offY * v.scale)) / v.scale;
}

bool EntityRes::InScreen(EntityRes* pEntityRes, float x, float y)
{
	auto& v = *pEntityRes->pView;
	float screenX = x * v.scale - floorf(v.offX * v.scale);
	float screenY = y * v.scale - floorf(v.offY * v.scale);
	return screenX >= 0 && screenX <= v.window_w &&
		screenY >= 0 && screenY <= v.window_h;
}

void EntityRes::GridTouch(EntityRes* entityRes, std::weak_ptr<Entity> e, EntityLayer* targetLayer)
{
	auto we = e.lock();
	if (!we)
		return;
	if (!we->entityLayer)
		return;
	EntityLayer* eL = nullptr;
	if (targetLayer)
		eL = targetLayer;
	else
		eL = we->entityLayer;
	float adjustVal = 0.01f;//调整

	SDL_FRect qtRect;
	qtRect.x = we->x - we->cbRect.left - adjustVal;
	qtRect.y = we->y - we->cbRect.top - adjustVal;
	qtRect.w = we->cbRect.left + we->cbRect.right + 2 * adjustVal;
	qtRect.h = we->cbRect.top + we->cbRect.bottom + 2 * adjustVal;
	//使用和地图的相交矩形
	SDL_FRect sdlSrc, intersectRect;
	sdlSrc.x = 0;
	sdlSrc.y = 0;
	sdlSrc.w = *entityRes->pMapW * 16.0f;
	sdlSrc.h = *entityRes->pMapH * 16.0f;
	//计算相交矩形
	if (SDL_IntersectFRect(&sdlSrc, &qtRect, &intersectRect) == SDL_TRUE)
	{
		static std::vector<Entity*> quadTreeRes;
		quadTreeRes.clear();
		eL->quadTree->query((Rect<float>&)intersectRect, quadTreeRes);
		for (auto& e : quadTreeRes)
		{
			auto wdst = e->self.lock();
			if (wdst)
			{
				if (wdst == we)
					continue;
				we->AddTouchList(wdst);
			}
		}
	}
}

void EntityRes::ClearLightList()
{
	lightList.clear();
}

void EntityRes::DrawLightEntity(MyMapLayer* pLayer, bool playing)
{
	//绘制光线贴图
	for (auto& e : lightList)
	{
		auto we = e.lock();
		if (we)
		{
			auto layerSrc = (MyMapLayer*)we->light.layer;
			//如果该实体在图层的后面，则不绘制
			if (layerSrc->order > pLayer->order)
				continue;
			float lightAlpha;
			//同层用原值，其他层用lightConst
			if (layerSrc->order == pLayer->order)
				lightAlpha = 1.0f;
			else
				lightAlpha = pLayer->lightConst;
			//这里使用color顶点颜色储存alpha，为了一口气全部绘制
			we->color = RGBA(0xff, 0xff, 0xff, (BYTE)(0xff * lightAlpha));
			//图层跟随移动
			MyView srcView = *pView;
			if (layerSrc->layerType == 1)
			{
				pView->offX += layerSrc->offx;
				pView->offY += layerSrc->offy;
				if (playing)
				{
					float farValue = MyFar(layerSrc->myFar);//计算随距离增加，眼睛中物体移动距离
					pView->offX -= (1 - farValue) * pView->offX;
					pView->offY -= (1 - farValue) * pView->offY;
				}
			}
			if (we->shader.usingShader)
				DrawShaderEntity(we);
			else
				DrawAddEntity(we);
			if (layerSrc->layerType == 1)
				*pView = srcView;
		}
	}
	DrawEntity();
}

void EntityRes::MarkLightEntity(MyMapLayer* pLayer)
{
	EntityLayer* entityLayer = GetEntityLayer(pLayer);
	for (auto& e : entityLayer->Ls)
	{
		if (e->light.usingLight)
		{
			e->light.layer = pLayer;
			lightList.push_back(e);
		}
	}
	for (auto& e : entityLayer->Am)
	{
		if (e->light.usingLight)
		{
			e->light.layer = pLayer;
			lightList.push_back(e);
		}
	}

	for (auto& e : entityLayer->Pe)
	{
		if (e->light.usingLight)
		{
			e->light.layer = pLayer;
			lightList.push_back(e);
		}
	}
}

PathCell* EntityRes::GetPath(std::weak_ptr<Entity> e, float dstX, float dstY, float srcX, float srcY)
{
	auto we = e.lock();
	if (we)
	{
		auto pEntityRes = (EntityRes*)we->gameFunc->entityRes;
		auto entityLayer = (EntityLayer*)we->entityLayer;
		auto iter = pEntityRes->pfSys.find(entityLayer);
		int mapW = *pEntityRes->pMapW;
		int mapH = *pEntityRes->pMapH;
		if (iter != pEntityRes->pfSys.end())
		{
			auto pathGrid = iter->second.GetPath((WORD)dstX, (WORD)dstY);
			if (srcX >= 0 && srcX < mapW && srcY >= 0 && srcY < mapH)
			{
				PathCell* c = &pathGrid->vecMap.at(*pEntityRes->pMapW * (WORD)srcY + (WORD)srcX);
				if (c->dis <= mapW * mapH)
					return c;
				else
					return &zeroCell;
			}
		}
		else
		{
			pEntityRes->pfSys.insert(std::make_pair(entityLayer, PathfindingE()));
			PathfindingE* p = &pEntityRes->pfSys.at(entityLayer);
			p->Init(*pEntityRes->pMapW, *pEntityRes->pMapH, we->mapLayer, we->cbRect.pxmArr, we->cbRect.pxaArr, we->cbRect.pxmArr_w);
			auto pathGrid = p->GetPath((WORD)dstX, (WORD)dstY);
			if (srcX >= 0 && srcX < mapW && srcY >= 0 && srcY < mapH)
			{
				PathCell* c = &pathGrid->vecMap.at(*pEntityRes->pMapW * (WORD)srcY + (WORD)srcX);
				if (c->dis <= mapW * mapH)
					return c;
				else
					return &zeroCell;
			}
		}
	}
    return &zeroCell;
}

bool EntityRes::LineTest(std::weak_ptr<Entity> e, float srcX, float srcY, float dstX, float dstY)
{
	auto we = e.lock();
	if (we && we->cbRect.pxmArr)
	{
		auto pEntityRes = (EntityRes*)we->gameFunc->entityRes;
		auto entityLayer = (EntityLayer*)we->entityLayer;
		auto iter = pEntityRes->pfSys.find(entityLayer);
		if (iter == pEntityRes->pfSys.end())
			GetPath(e, dstX, dstY, srcX, srcY);
		PathfindingE* p = &pEntityRes->pfSys.at(entityLayer);
		return p->LineBlock(floorf(srcX), floorf(srcY), floorf(dstX), floorf(dstY), &PathfindingE::CellProc);
	}
	return false;
}

void EntityRes::UpdatePathFinder()
{
	for (auto& p : pfSys)
		p.second.UpdateMapData();
}

void EntityRes::GetMapSize(EntityRes* pEntityRes, int* outMapW, int* outMapH)
{
	*outMapW = *pEntityRes->pMapW;
	*outMapH = *pEntityRes->pMapH;
}

void EntityRes::GridRemoveEntity(std::shared_ptr<Entity>& we)
{
	if (we->type == 3)
		return;
	if (!we->entityLayer)
		return;
	if (!we->cbRect.pxmArr)
		return;
	auto iter = we->entityLayer->treeCheck.find(we.get());
	if (iter != we->entityLayer->treeCheck.end())
	{
		we->entityLayer->quadTree->remove(we.get());
		we->entityLayer->treeCheck.erase(we.get());
	}
}

void EntityRes::GridSetEntity(std::shared_ptr<Entity>& we)
{
	if (we->type == 3)
		return;
	if (!we->entityLayer)
		return;
	if (!we->cbRect.pxmArr)
		return;
	auto iter = we->entityLayer->treeCheck.find(we.get());
	if (iter == we->entityLayer->treeCheck.end())
	{
		//更新矩形
		auto& qtRect = we->cbRect.qtRect;
		qtRect.x = we->x - we->cbRect.left;
		qtRect.y = we->y - we->cbRect.top;
		qtRect.w = we->cbRect.left + we->cbRect.right;
		qtRect.h = we->cbRect.top + we->cbRect.bottom;
		//使用和地图的相交矩形
		int mapW, mapH;
		gameFunc.GetMapSize(gameFunc.mapSizeGetter, &mapW, &mapH);
		SDL_FRect sdlSrc, intersectRect;
		sdlSrc.x = 0;
		sdlSrc.y = 0;
		sdlSrc.w = mapW * 16.0f;
		sdlSrc.h = mapH * 16.0f;
		//计算相交矩形
		if (SDL_IntersectFRect(&sdlSrc, &qtRect, &intersectRect) == SDL_TRUE)
		{
			qtRect = intersectRect;
			we->entityLayer->treeCheck.insert(we.get());
			we->entityLayer->quadTree->add(we.get());
		}
	}
}

MyTextureAndSRV* EntityRes::GetPidTexture(CString pidName)
{
	auto iter = loadedPidTexture.find(pidName.GetString());
	if (iter == loadedPidTexture.end())
	{
		//单文件名
		std::vector<char> utf8;
		CString wbuff;
		bool languageFolder = false;
		if (entityLanguage.GetLength() == 0 || entityLanguage == L"默认")
		{
			wbuff.Format(L"./data/pid/%s.png", pidName.GetString());
		}	
		else
		{
			wbuff.Format(L"./data/language/%s/pid/%s.png", entityLanguage.GetString(), pidName.GetString());
			languageFolder = true;
		}
		UTF16ToUTF8(wbuff.GetString(), &utf8);
		MyTextureAndSRV tas;
		FILE* fp = nullptr;
		if (languageFolder)
		{
			//确认翻译文件是否存在
			fopen_s(&fp, utf8.data(), "rb");
		}
		if (!fp)
		{
			//翻译文件不存在，使用默认文件
			wbuff.Format(L"./data/pid/%s.png", pidName.GetString());
			UTF16ToUTF8(wbuff.GetString(), &utf8);
			fopen_s(&fp, utf8.data(), "rb");
		}
		if (fp)
		{
			fclose(fp);
			MyTextureAndSRV tas;
			pRenderer->MyLoadTexture(&tas.pTexture, utf8.data());
			pRenderer->MyCreateShaderResourceView(&tas.pSRV, tas.pTexture);
			loadedPidTexture.insert(std::make_pair(pidName.GetString(), tas));
			return &loadedPidTexture.at(pidName.GetString());
		}
		return nullptr;
	}
	return &iter->second;
}

SDL_FRect& GetRect(const void* myData)
{
	Entity* e = (Entity*)myData;
	return e->cbRect.qtRect;
}

EntityLayer* EntityRes::GetEntityLayer(MyMapLayer* pLayer)
{
	auto iter = loadedEntity.find(pLayer);
	if (iter == loadedEntity.end())
	{
		loadedEntity.insert(std::make_pair(pLayer, EntityLayer()));
		auto& entityLayer = loadedEntity.at(pLayer);
		//设置该层的四叉树
		if (entityLayer.quadTree)
			delete entityLayer.quadTree;
		entityLayer.quadTree = new Quadtree<Entity*, GetRectEntity>({ 0,0,*pMapW * 16.0f ,*pMapH * 16.0f });
		for (auto& p : *pLayer->GetPxeStep())
		{
			auto e = LoadEntity(&p.second, pLayer, &entityLayer);
		}
		return &entityLayer;
	}
	return &iter->second;
}

std::weak_ptr<Entity> EntityRes::LoadEntity(const EntityLoad* el, MyMapLayer* pLayer, EntityLayer* entityLayer)
{
	std::shared_ptr<Entity> we = GameCreateEntity(el->name.c_str());
	if (!we)
		return std::weak_ptr<Entity>();
	we->el = *el;
	we->x = el->x * pView->grid_w + 8;
	we->y = el->y * pView->grid_h + 8;
	we->SetState(0, el->flag.lr);
	//使用简易设置动画
	if (we->el.flag.simpAni)
	{
		we->ani.png = we->el.eid;
		we->ani.sprite_index = we->el.eventName;
	}
	//实体分类
	switch (we->type)
	{
	default:
	case 0://实体
		entityLayer->Ls.push_back(we);
		break;
	case 1://玩家
		break;
	case 2://弹药
		entityLayer->Am.push_back(we);
		break;
	case 3://粒子
		entityLayer->Pe.push_back(we);
		break;
	}
	we->mapLayer = pLayer;
	we->entityLayer = entityLayer;
	we->gameFunc = &gameFunc;
	if (!we->initCheck)
		we->Init(we);
	return we;
}

void EntityRes::LoadEntityDll()
{
	//加载所有dll
	WIN32_FIND_DATAW findData;
	HANDLE hFind = INVALID_HANDLE_VALUE;
	hFind = FindFirstFileW(L".\\data\\entity\\*.dll", &findData);
	if (hFind == INVALID_HANDLE_VALUE)
	{
		MessageBoxW(AfxGetApp()->GetMainWnd()->m_hWnd, L"加载实体Dll失败", L"", MB_ICONERROR);
		exit(0);
	}
	do
	{
		if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
		{
			loadedEntityDll.insert(std::make_pair(findData.cFileName, EntityDll()));
			auto& entityDll = loadedEntityDll.at(findData.cFileName);
			for (int i = (int)wcslen(findData.cFileName); i > 0; i--)
			{
				if (findData.cFileName[i] == L'.')
				{
					findData.cFileName[i] = 0;
					break;
				}
			}
			entityDll.Load(findData.cFileName);
		}
	} while (FindNextFileW(hFind, &findData));
	FindClose(hFind);
}

std::shared_ptr<Entity> EntityRes::GameCreateEntity(const wchar_t* name)
{
	for (auto& p : loadedEntityDll)
	{
		std::shared_ptr<Entity> we;
		p.second._GameCreateEntity(name, &we);
		if (!we)
			continue;
		return we;
	}
	//错误找不到实体
	wchar_t err[MAX_PATH];
	swprintf_s(err, L"找不到实体%s", name);
	MessageBoxW(AfxGetApp()->GetMainWnd()->m_hWnd, err, L"创建实体失败", MB_ICONWARNING);
	//尝试创建null实体
	name = L"null";
	for (auto& p : loadedEntityDll)
	{
		std::shared_ptr<Entity> we;
		p.second._GameCreateEntity(name, &we);
		if (!we)
			continue;
		return we;
	}
	swprintf_s(err, L"找不到实体%s", name);
	MessageBoxW(AfxGetApp()->GetMainWnd()->m_hWnd, err, L"创建实体失败", MB_ICONWARNING);
	exit(0);
}

void EntityRes::EntityAniStep(std::shared_ptr<Entity>& we)
{
	if (we->ani.png[0] == 0 || we->ani.sprite_index[0] == 0)
		return;
	auto pidData = gamePid.GetPid(we->ani.png.c_str());
	if (pidData->aniList.empty())
		return;
	auto iter = pidData->aniList.find(we->ani.sprite_index);
	if (iter == pidData->aniList.end())
	{
		err.Format(L"%s没有动画%s", we->ani.png.c_str(), we->ani.sprite_index.c_str());
		return;
//		e->ani.sprite_index[0] = 0;
//#ifdef DEBUG
//		wchar_t err[MAX_PATH];
//		swprintf_s(err, L"%s没有动画%s", e->ani.png.c_str(), e->ani.sprite_index.c_str());
//		FILE* fp = nullptr;
//		_wfopen_s(&fp, L"error.txt", L"a");
//		if (fp)
//		{
//			std::vector<char> utf8;
//			UTF16ToUTF8(err, &utf8);
//			utf8.push_back('\r');
//			utf8.push_back('\n');
//			fwrite(utf8.data(), utf8.size(), 1, fp);
//			fclose(fp);
//		}
//		MessageBoxW(AfxGetApp()->GetMainWnd()->m_hWnd, err, L"资源错误", MB_ICONWARNING);
//#else
//		return;
//#endif // DEBUG
	}
	AniPrep* aniPrep = &iter->second;
	if (aniPrep->layerList.empty() || aniPrep->layerList.front().frameList.empty())
		return;
	int len = (int)aniPrep->layerList.front().frameList.size();
	if (aniPrep->speed > 0)
	{
		if (we->ani.image_counter >= aniPrep->speed)
		{
			we->ani.image_counter = 0;
			if (aniPrep->loop || we->ani.image_index < len - 1)
				we->ani.image_index++;
			if (we->ani.image_index >= len)
				if (aniPrep->loop)
					we->ani.image_index = 0;
				else
					we->ani.image_index = len - 1;
		}
		we->ani.image_counter += we->ani.image_counter_speed;
	}
}

void EntityRes::ClearTexture(std::unordered_map<std::wstring, MyTextureAndSRV>* textureRes)
{
	for (auto& p : *textureRes)
	{
		auto& tas = p.second;
		if (tas.pSRV)
			tas.pSRV->Release();
		if (tas.pTexture)
			tas.pTexture->Release();
	}
	textureRes->clear();
}

void EntityRes::DrawAddEntityCbRect(std::weak_ptr<Entity> e, DWORD c)
{
	auto we = e.lock();
	if (we)
	{
		MyRect rc;
		rc.left = (we->x - we->cbRect.left) * pView->scale - floorf(pView->offX * pView->scale);
		rc.right = (we->x + we->cbRect.right) * pView->scale - floorf(pView->offX * pView->scale);
		rc.top = (we->y - we->cbRect.top) * pView->scale - floorf(pView->offY * pView->scale);
		rc.bottom = (we->y + we->cbRect.bottom) * pView->scale - floorf(pView->offY * pView->scale);
		pRenderer->AddRect(&rc, c);
	}
}

ID3D11Texture2D* EntityRes::GetPreTexture(UINT w, UINT h)
{
	if (w > preTexture.w || h > preTexture.h)
	{
		pRenderer->SetBufferSize(w, h, &preTexture, "preTexture");
	}
	if (preTexture.pBuffer == nullptr)
	{
		pRenderer->SetBufferSize(w, h, &preTexture, "preTexture");
	}
	return preTexture.pBuffer;
}

void EntityRes::GridItemTarget(std::shared_ptr<Entity>& we)
{
	if (!we->entityLayer)
		return;
	SDL_FRect qtRect;
	qtRect.x = we->x - we->cbRect.left;
	qtRect.y = we->y - we->cbRect.top;
	qtRect.w = we->cbRect.left + we->cbRect.right;
	qtRect.h = we->cbRect.top + we->cbRect.bottom;
	//使用和地图的相交矩形
	SDL_FRect sdlSrc, intersectRect;
	sdlSrc.x = 0;
	sdlSrc.y = 0;
	sdlSrc.w = *pMapW * 16.0f;
	sdlSrc.h = *pMapH * 16.0f;
	//计算相交矩形
	if (SDL_IntersectFRect(&sdlSrc, &qtRect, &intersectRect) == SDL_TRUE)
	{
		static std::vector<Entity*> quadTreeRes;
		quadTreeRes.clear();
		we->entityLayer->quadTree->query((Rect<float>&)intersectRect, quadTreeRes);
		for (auto& e : quadTreeRes)
		{
			auto wdst = e->self.lock();
			if (wdst)
			{
				if (wdst == we)
					continue;
				if (we->Item(wdst))
					wdst->Gain(we);
			}
		}
	}
}

bool EntityRes::GridAmTarget(std::shared_ptr<Entity>& we)
{
	if (!we->entityLayer)
		return false;
	float adjustVal = 0.01f;//调整
	SDL_FRect qtRect;
	qtRect.x = we->x - we->cbRect.left - adjustVal;
	qtRect.y = we->y - we->cbRect.top - adjustVal;
	qtRect.w = we->cbRect.left + we->cbRect.right + 2 * adjustVal;
	qtRect.h = we->cbRect.top + we->cbRect.bottom + 2 * adjustVal;
	//使用和地图的相交矩形
	SDL_FRect sdlSrc, intersectRect;
	sdlSrc.x = 0;
	sdlSrc.y = 0;
	sdlSrc.w = *pMapW * 16.0f;
	sdlSrc.h = *pMapH * 16.0f;
	//计算相交矩形
	if (SDL_IntersectFRect(&sdlSrc, &qtRect, &intersectRect) == SDL_TRUE)
	{
		static std::vector<Entity*> quadTreeRes;
		quadTreeRes.clear();
		we->entityLayer->quadTree->query((Rect<float>&)intersectRect, quadTreeRes);
		for (auto& e : quadTreeRes)
		{
			auto wdst = e->self.lock();
			if (wdst)
			{
				if (wdst->hide)
					continue;
				if (wdst->type == 3)
					continue;
				if (AmTarget(we, wdst))
					return true;
			}
		}
	}
	return false;
}

void EntityRes::DecodeRecord(const wchar_t* recordStr, const void** outInputArr, size_t* outDataSize)
{
	static std::vector<BYTE> outData;
	std::vector<char> buff;
	std::vector<BYTE> compressData;
	UTF16ToUTF8(recordStr, &buff);
	Base64Decode(compressData, buff.data());
	ZLibUncompressData(&outData, outDataSize, compressData.data(), compressData.size());
	*outInputArr = outData.data();
}
