459 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			459 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| /*
 | |
| 文件名: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;
 | |
| 
 | |
|     //所属城镇
 | |
|     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, -120 - 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 - 120 - 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);
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
|     //添加对象
 | |
|     function AddObject(obj, IsPlayer = false) {
 | |
|         //角色对象
 | |
|         if (typeof obj == "character") {
 | |
|             //如果已经处于某个地图中
 | |
|             if (obj.Parent) {
 | |
|                 obj.Parent.Removechild(obj);
 | |
|             }
 | |
|             LayerObject.normal.Addchild(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;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //移动城镇的添加对象
 | |
|     function AddObjectByChangeTown(obj, FromMapobj) {
 | |
|         //角色对象
 | |
|         if (typeof obj == "character") {
 | |
|             //如果已经处于某个地图中
 | |
|             if (obj.Parent) {
 | |
|                 obj.Parent.Removechild(obj);
 | |
|             }
 | |
|             LayerObject.normal.Addchild(obj);
 | |
|             //将地图信息写入角色中
 | |
|             obj.MySelfMap = this.weakref();
 | |
|             //绑定摄像机
 | |
|             m_camera.SetFromParent(obj);
 | |
|             //获取应该设置的坐标
 | |
|             foreach(index, info in m_data.town_movable_area_info) {
 | |
|                 if (info.town == FromMapobj.m_town && info.area == FromMapobj.m_mapId) {
 | |
|                     local pos = {
 | |
|                         x = m_data.town_movable_area[index * 4] + m_data.town_movable_area[index * 4 + 2] / 2,
 | |
|                         y = m_data.town_movable_area[index * 4 + 1] + m_data.town_movable_area[index * 4 + 3] / 2,
 | |
|                         z = 0
 | |
|                     }
 | |
|                     obj.SetPosition(pos);
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             //获取当前场景
 | |
|             local Stage = sq_GetCurrentStage();
 | |
|             if (GlobalTownManager.CurrentTown) {
 | |
|                 Stage.Removechild(GlobalTownManager.CurrentTown);
 | |
|             }
 | |
|             Stage.Addchild(this);
 | |
|             //添加全局
 | |
|             GlobalTownManager.CurrentTown = this.weakref();
 | |
| 
 | |
| 
 | |
|             //背景音乐处理
 | |
|             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;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     constructor(arg) {
 | |
|         base.constructor();
 | |
| 
 | |
|         if (typeof arg == "integer") {
 | |
| 
 | |
|         } else if (typeof arg == "string") {
 | |
|             InitData(arg);
 | |
|         }
 | |
| 
 | |
|         //初始化摄像机
 | |
|         m_camera = MapCamera(this);
 | |
| 
 | |
|         //初始化图层
 | |
|         InitLayer();
 | |
| 
 | |
|         //初始化地板
 | |
|         InitTile();
 | |
|         //初始化背景动画
 | |
|         InitBackgroundAnimation();
 | |
|         //初始化场景Ani
 | |
|         InitAnimation();
 | |
| 
 | |
|         //设置摄像机的最大可行区域
 | |
|         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 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];
 | |
|                 MapObj.AddObjectByChangeTown(obj, this);
 | |
|                 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();
 | |
|     }
 | |
| } |