/* 文件名:MapObject.nut 路径:User/Object/Map/MapObject.nut 创建日期:2024-11-22 19:40 文件用途:地图对象 */ class MapLayer extends Actor { function _typeof() { return "townmap"; } } class Map extends Actor { //图层对象Map LayerObject = null; //角色列表 PlayerList = null; //所属城镇 m_town = 0; //地图编号 m_mapId = 0; //数据 m_data = null; //地图长度 m_length = 0; //地图高度 m_height = 0; //摄像机 m_camera = null; //地图的摄像机最大可移动参数 CameraMovableAreaX = null; CameraMovableAreaY = null; //背景音乐 BackGroundMusic = null; function _typeof() { return "townmap"; } //初始化图层对象 function InitLayer() { //图层ObjMap LayerObject = { contact = MapLayer(), distantback = MapLayer(), middleback = MapLayer(), bottom = MapLayer(), closeback = MapLayer(), normal = MapLayer(), close = MapLayer(), cover = MapLayer(), max = MapLayer() }; //把所有图层Obj挂上Map的子对象 foreach(LayerObj in LayerObject) { Addchild(LayerObj); } local FristOrder = 10000; //按照层级给Layer设置层级 LayerObject.contact.SetZOrder(FristOrder); FristOrder += 50000; LayerObject.distantback.SetZOrder(FristOrder); FristOrder += 50000; LayerObject.middleback.SetZOrder(FristOrder); FristOrder += 50000; LayerObject.bottom.SetZOrder(FristOrder); FristOrder += 50000; LayerObject.closeback.SetZOrder(FristOrder); FristOrder += 50000; LayerObject.normal.SetZOrder(FristOrder); FristOrder += 50000; LayerObject.close.SetZOrder(FristOrder); FristOrder += 50000; LayerObject.cover.SetZOrder(FristOrder); FristOrder += 50000; LayerObject.max.SetZOrder(FristOrder); }; //初始化数据 function InitData(path) { m_data = ScriptData.GetFileData(path, function(DataTable, Data) { //在这里添加一些初始化的默认值 DataTable.wide_mode_camer_vertical_correction <- 0; DataTable.background_pos <- 80; while (!Data.Eof()) { local str = Data.Get(); if (str == "[background pos]") { DataTable.background_pos <- (Data.Get()); } else if (str == "[map name]") { DataTable.name <- Data.Get(); } else if (str == "[wide mode camera vertical correction]") { DataTable.wide_mode_camer_vertical_correction <- Data.Get(); } else if (str == "[tile]") { DataTable.tile <- []; while (true) { local tiledata = Data.Get(); if (tiledata == "[/tile]") break; DataTable.tile.push(tiledata); } } else if (str == "[extended tile]") { DataTable.extended_tile <- []; while (true) { local tiledata = Data.Get(); if (tiledata == "[/extended tile]") break; DataTable.extended_tile.push(tiledata); } } else if (str == "[far sight scroll]") { DataTable.far_sight_scroll <- (Data.Get()); } else if (str == "[background animation]") { DataTable.background_animation <- []; while (true) { local anidata = Data.Get(); if (anidata == "[/background animation]") break; if (anidata == "[ani info]") { local info = {}; Data.Get(); info["filename"] <- Data.Get(); Data.Get(); info["layer"] <- Data.Get().slice(1, -1); Data.Get(); info["order"] <- Data.Get(); DataTable.background_animation.push(info); } } } else if (str == "[sound]") { DataTable.sound <- []; while (true) { local sounddata = Data.Get(); if (sounddata == "[/sound]") break; DataTable.sound.push(sounddata); } } else if (str == "[animation]") { DataTable.animation <- []; while (true) { local anidata = Data.Get(); if (anidata == "[/animation]") break; local info = {}; info["filename"] <- anidata; info["layer"] <- Data.Get().slice(1, -1); info["xpos"] <- Data.Get(); info["ypos"] <- Data.Get(); info["zpos"] <- Data.Get(); DataTable.animation.push(info); } } else if (str == "[NPC]") { DataTable.npc <- []; while (true) { local npcdata = Data.Get(); if (npcdata == "[/NPC]") break; local info = {}; info["id"] <- npcdata; info["direction"] <- Data.Get(); info["xpos"] <- Data.Get(); info["ypos"] <- Data.Get(); info["zpos"] <- Data.Get(); DataTable.npc.push(info); } } else if (str == "[town movable area]") { DataTable.town_movable_area <- []; DataTable.town_movable_area_info <- []; while (true) { local areadata = Data.Get(); if (areadata == "[/town movable area]") break; DataTable.town_movable_area.push(areadata); for (local i = 0; i< 3; i++) { DataTable.town_movable_area.push(Data.Get()); } local T = { town = Data.Get(), area = Data.Get(), } DataTable.town_movable_area_info.push(T); } } else if (str == "[virtual movable area]") { DataTable.virtual_movable_area <- []; while (true) { local areadata = Data.Get(); if (areadata == "[/virtual movable area]") break; DataTable.virtual_movable_area.push(areadata); DataTable.virtual_movable_area.push(Data.Get()); DataTable.virtual_movable_area.push(Data.Get()); DataTable.virtual_movable_area.push(Data.Get()); } } } }); m_data.path <- path; m_data.dirpath <- path.slice(0, path.lastfind("/") + 1); } //初始化地板 function InitTile() { local NormalTileCount = 0; //普通地板 if ("tile" in m_data) { NormalTileCount = m_data.tile.len(); //计算地图长度 m_length = NormalTileCount * 224; foreach(pos, path in m_data.tile) { local realpath = m_data.dirpath + path.tolower(); local TileObj = Tile(realpath); TileObj.SetAnchor(0.0, 0.0); TileObj.SetPosition(pos * 224, -200 - m_data.background_pos); LayerObject.bottom.Addchild(TileObj); } //默认地板 + 摄像机偏移 + 默认需要有一个40的添加地板 m_height = 560; } //补充地板 if ("extended_tile" in m_data) { local ExTileCount = m_data.extended_tile.len(); //计算地图高度 local Buffer = (ExTileCount / NormalTileCount); //这里默认加了40的高度 然后要读取pvf的 [wide mode camera vertical correction] m_height += (Buffer< 1 ? 1 : Buffer) * 40; foreach(pos, path in m_data.extended_tile) { local realpath = m_data.dirpath + path.tolower(); local TileObj = Tile(realpath); TileObj.SetAnchor(0.0, 0.0); //根据基础地板的数量判断是第几排 TileObj.SetPosition((pos % NormalTileCount) * 224, 560 - 200 - m_data.background_pos + ((pos / NormalTileCount) * 40)); LayerObject.bottom.Addchild(TileObj); } } } //初始化背景动画 function InitBackgroundAnimation() { local Rate = m_data.rawin("far_sight_scroll") ? (m_data.far_sight_scroll.tofloat() / 100.0) : 1.0; m_camera.BackgroundMoveSpeed = Rate; //背景动画 if ("background_animation" in m_data) { foreach(Info in m_data.background_animation) { local realpath = m_data.dirpath + Info.filename.tolower(); //先构造一个天空 然后通过宽度 和地图宽度得知还需要再构造多少个 local AniList = []; local AniObj = Animation(realpath); local width = AniObj.GetSize().w; AniList.push(AniObj); for (local i = 1; i<((m_length * Rate) / width + 1); i++) { local AniObj = Animation(realpath); AniList.push(AniObj); } foreach(pos, ani in AniList) { ani.SetAnchor(0.0, 0.0); ani.SetPosition(pos * AniObj.GetSize().w, -120); LayerObject[Info.layer].Addchild(ani); ani.SetZOrder(-1000000); } } } } //初始化场景Ani function InitAnimation() { foreach(pos, info in m_data.animation) { local realpath = m_data.dirpath + info.filename.tolower(); local AniObj = AnimationObject(realpath); AniObj.SetAnchor(0.0, 0.0); if (info.layer != "normal") AniObj.SetPositionNoLayer(info.xpos, info.ypos, info.zpos); else AniObj.SetPosition(info.xpos, info.ypos, info.zpos); LayerObject[info.layer].Addchild(AniObj); } } //初始化NPC function InitNPC() { if (!m_data.rawin("npc")) return; local Arr = []; foreach(pos, info in m_data.npc) { local NPCobj = GameObject.NPC(info.id); NPCobj.SetDirection(info.direction); NPCobj.SetPosition(info.xpos, info.ypos, info.zpos); Arr.push(NPCobj); AddObject(NPCobj); } //构造完成直接赋值对象 m_data.npc = Arr; } //添加对象 function AddObject(obj, IsPlayer = false) { //角色对象 if (typeof obj == "character") { //如果已经处于某个地图中 if (obj.Parent) { obj.Parent.Removechild(obj); } LayerObject.normal.Addchild(obj); PlayerList[obj.Cid] <- obj; obj.MySelfMap = this.weakref(); //如果是玩家自己 if (IsPlayer) { m_camera.SetFromParent(obj); if (BackGroundMusic == null) BackGroundMusic = {}; foreach(SoundName in m_data.sound) { local BgMusic = Audio(getconsttable().MUSIC[SoundName]); BgMusic.Play(); BackGroundMusic[SoundName] <- BgMusic; } } } else if (typeof obj == "npc") { LayerObject.normal.Addchild(obj); } } //移除对象 function RemoveObject(obj) { //图层对象中移除玩家 LayerObject.normal.Removechild(obj); //玩家列表中移除玩家 PlayerList.rawdelete(obj.Cid); //角色对象 if (typeof obj == "character") { //将地图信息写入角色中 obj.MySelfMap = null; } } //移除地图中所有的角色对象 function RemoveAllCharacterObject() { foreach(obj in PlayerList) { //角色对象 if (typeof obj == "character") { RemoveObject(obj); } } } //移动城镇的添加对象 function AddObjectByChangeTown(obj, pos) { //角色对象 if (typeof obj == "character") { //角色原城镇 local FromMapobj = obj.MySelfMap; //清除原城镇里的玩家 FromMapobj.RemoveAllCharacterObject(); //背景音乐处理 BackGroundMusic = {}; if (FromMapobj.BackGroundMusic != null) { //把老地图的音频先获取过来 foreach(SoundName, Music in FromMapobj.BackGroundMusic) { //如果有背景音乐是新地图存在的 就添加 if (this.m_data.sound.find(SoundName) != null) { BackGroundMusic[SoundName] <- Music; } } //销毁老地图的音频列表 FromMapobj.BackGroundMusic = null; //检查当前地图的背景音乐 foreach(SoundName in this.m_data.sound) { //如果有一个背景音乐是新地图不存在的 就停止播放 if (!(BackGroundMusic.rawin(SoundName))) { local BgMusic = Audio(getconsttable().MUSIC[SoundName]); BgMusic.Play(); BackGroundMusic[SoundName] <- BgMusic; } } } //绑定摄像机 m_camera.SetFromParent(obj); //获取当前场景 local Stage = sq_GetCurrentStage(); if (GlobalTownManager.CurrentMap) { Stage.Removechild(GlobalTownManager.CurrentMap); } Stage.Addchild(this); //添加全局 GlobalTownManager.CurrentMap = this.weakref(); //如果已经处于某个地图中 则先移除 if (obj.Parent) { obj.Parent.Removechild(obj); } //将角色添加到地图的normal图层 LayerObject.normal.Addchild(obj); PlayerList[obj.Cid] <- obj; //设置坐标 obj.SetPosition(pos); //将地图信息写入角色中 obj.MySelfMap = this.weakref(); } } constructor(arg) { PlayerList = {}; base.constructor(); if (typeof arg == "integer") { } else if (typeof arg == "string") { InitData(arg); } //初始化摄像机 m_camera = MapCamera(this); //初始化图层 InitLayer(); //初始化地板 InitTile(); //初始化背景动画 InitBackgroundAnimation(); //初始化场景Ani InitAnimation(); //初始化NPC InitNPC(); //注册鼠标判定逻辑 Reg_Yosin_Mouse_Logic("MapMLg_" + C_Object, OnMouseLogic.bindenv(this)); //设置摄像机的最大可行区域 m_camera.MovableAreaX = m_length; m_camera.MovableAreaY = m_height - m_data.wide_mode_camer_vertical_correction; m_camera.BackgroundOffset = m_data.background_pos; // OpenMovableAreaBorder(); } //DEBUG方法 function OpenMovableAreaBorder() { for (local i = 0; i< m_data.virtual_movable_area.len(); i += 4) { local x = m_data.virtual_movable_area[i]; local y = m_data.virtual_movable_area[i + 1]; local w = m_data.virtual_movable_area[i + 2]; local h = m_data.virtual_movable_area[i + 3]; local Ac = Actor(); Ac.SetPosition(x, y); Ac.SetSize(w, h); Ac.ShowBorder(true); LayerObject.max.Addchild(Ac); } } function OnMouseLogic(MouseState, Wheel, MousePos_X, MousePos_Y) { //判断是人物所在的地图 if (ClientCharacter && this.C_Object == ClientCharacter.MySelfMap.C_Object) { local Arr = []; //遍历全部NPC位置 foreach(index, Npcobj in m_data.npc) { //获取NPC的屏幕位置 local NPCpos = Npcobj.GetWorldPosition(); //在屏幕中的才添加比对 这里只判断了X轴 if (NPCpos.x > -20 && NPCpos.y< 1086) { Arr.push(NPCpos.x - Npcobj.IdentifyWidth / 2); Arr.push(NPCpos.y - Npcobj.IdentifyHeight); Arr.push(Npcobj.IdentifyWidth); Arr.push(Npcobj.IdentifyHeight); } } local Index = Math.PointIsInWhichRectangle(MousePos_X, MousePos_Y, Arr); //有事件发生的NPC对象 if (Index != -1) { return m_data.npc[Index].OnMouseLogic(MouseState, Wheel, MousePos_X, MousePos_Y); } else { foreach(Npcobj in m_data.npc) { Npcobj.OutMouseLogic(); } return null; } } return null; } //判断区域是否可行 function CheckMovableArea(gx, gxoffset, gy, gyoffset) { local pos = { x = gxoffset, y = gyoffset } //都符合 if (Math.PointIsInSquare(gx + gxoffset, gy + gyoffset, m_data.virtual_movable_area)) {} //X符合 else if (Math.PointIsInSquare(gx + gxoffset, gy, m_data.virtual_movable_area)) { pos.y = 0; } //Y符合 else if (Math.PointIsInSquare(gx, gy + gyoffset, m_data.virtual_movable_area)) { pos.x = 0; } else { pos.x = 0; pos.y = 0; } return pos; } //判断区域是否传送 function CheckMovableAreaTransmit(obj, gx, gy) { local Index = Math.PointIsInWhichRectangle(gx, gy, m_data.town_movable_area); //走进了传送阵 if (Index != -1) { if (!obj.TransmitFlag) { //得到传送信息 目标城镇 local info = m_data.town_movable_area_info[Index]; //如果是未加载的城镇 则先构造城镇 if (!(GlobalTownManager.TownList.rawin(info.town))) { Town(info.town); } //计算位移过去以后应该设置的位置 local MapObj = GlobalTownManager.TownList[info.town].map[info.area]; local movepos = { z = 0 }; //遍历目标城镇的该区域 查找适当位移位置 foreach(index, mapinfo in MapObj.m_data.town_movable_area_info) { if (mapinfo.town == m_town && mapinfo.area == m_mapId) { movepos.x <- MapObj.m_data.town_movable_area[index * 4] + MapObj.m_data.town_movable_area[index * 4 + 2] / 2; movepos.y <- MapObj.m_data.town_movable_area[index * 4 + 1] + MapObj.m_data.town_movable_area[index * 4 + 3] / 2; break; } } //发包移动城镇 MySocket.Send(PACKET_ID.CHANGE_TOWN_AREA, { town = info.town, region = info.area, pos = movepos }) obj.TransmitFlag = true; } } else { obj.TransmitFlag = false; } } //音乐逻辑 function MusicLogic() { if (BackGroundMusic == null) return; foreach(Music in BackGroundMusic) { if (!Music.IsPlaying()) Music.Play(); } } function OnUpdate(Dt) { base.OnUpdate(Dt); //更新摄像机 m_camera.OnUpdate(Dt); //更新音乐逻辑 MusicLogic(); } }