zoukankan      html  css  js  c++  java
  • MMO可见格子算法

    看注释吧,写的很清楚了

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ZoneTest
    {
    	public class Zone
    	{
    		public int mId;
    		public float Width;
    		public float Height;
    		public List<Zone> VisibleZoneList = new List<Zone>();
    
    		public Zone(int id, float width, float height)
    		{
    			mId = id;
    			Width = width;
    			Height = height;
    		}
    
    		public void AddVisibleZone(Zone zone)
    		{
    			VisibleZoneList.Add(zone);
    		}
    	}
    	public class Scene
    	{
    		private List<Zone> mZoneList = new List<Zone>();
    
    		public Scene(float w,float h)
    		{
    			mSceneWidth = w;
    			mSceneHeight = h;
    		}
    		public const float ZONE_SIDE = 1.0f;
    		//场景宽高
    		private float mSceneWidth;
    		private float mSceneHeight;
    
    		//格子列数和行数
    		private int mZoneColumnCount;
    		private int mZoneLineCount;
    
    		public Zone GetZone(int id)
    		{
    			if (id < 0 || id > mZoneList.Count)
    			{
    				return null;
    			}
    			return mZoneList[id];
    		}
    
    
    		//Zone示意图
    		/*
    		|  mSceneWidth  |
    		-----------------           --
    		|	|	|	|	|ZONE_SIDE
    		-----------------
    		|	|	|	|	|
    		-----------------			mSceneHeight
    		|	|	|	|	|
    		-----------------			--
    		
    		 
    		  
    		  
    		----------------- line 0
    		
    		----------------- line 1
    		
    		----------------- line 2
    		
    		----------------- line 3
    
    		
    	column0 column1	  column2  column3
    		|		|		|		|
    		 		 		 	
    		|		|		|		|
    		 		 		 	
    		|		|		|		|
    		 		 		 	
    		|		|		|		|
    			
    		 * 
    		*/
    
    		public bool InitZone()
    		{
    			//计算场景内zone行和列
    			mZoneLineCount = (int)Math.Ceiling((double)mSceneHeight / (double)ZONE_SIDE);
    			mZoneColumnCount = (int)Math.Ceiling((double)mSceneWidth / (double)ZONE_SIDE);
    
    			//创建zone
    			for (int i = 0; i < mZoneLineCount; i++)
    			{
    				for (int j = 0; j < mZoneColumnCount; j++)
    				{
    					int id = i * mZoneColumnCount + j;
    					Zone zone = new Zone(id, ZONE_SIDE, ZONE_SIDE);
    					mZoneList.Add(zone);
    				}
    			}
    
    			//最大周围多少个格子被可见 MaxNearByZoneNumber*MaxNearByZoneNumber 个
    			const int MaxNearByZoneNumber = 3;
    			//可见格子的起始偏移
    			const int Offset = MaxNearByZoneNumber / 2;
    
    			//把周围可见格子加入列表
    			/*
    			 *     -------------
    			 * 	 |0	|1	|2	|
    			 * 	 -------------
    			 * 	 |3	|4	|5	|
    			 * 	 -------------
    			 * 	 |6	|7	|8	|
    			 *	 -------------
    			 */
    
    			//0的可见格子为 0134
    			//4的可见格子为 0123456789
    			//7的可见格子为 345678
    
    			//遍历所有格子行
    			for (int i = 0; i < mZoneLineCount; i++)
    			{
    				//遍历所有格子列
    				for (int j = 0; j < mZoneColumnCount; j++)
    				{
    					//当前要判断可见性的格子id
    					int id = i * mZoneColumnCount + j;
    					Zone zone = mZoneList[id];
    
    					//遍历周围 MaxNearByZoneNumber*MaxNearByZoneNumber个格子
    					//判断[x,y]这个格子是否出界
    
    					//行
    					for (int n = 0; n < MaxNearByZoneNumber; n++)
    					{
    						int y = i - Offset + n;
    						if (y < 0 || y >= mZoneLineCount) continue;//y出界
    
    						//列
    						for (int m = 0; m < MaxNearByZoneNumber; m++)
    						{
    
    							int x = j - Offset + m;
    							if (x < 0 || x >= mZoneColumnCount) continue;//x出界
    
    							//算当前格子id
    							int visibleZoneId = y * mZoneColumnCount + x;
    
    							//if (visibleZoneId == id) continue;//是自己格子也要加入,自己属于自己可见格子
    
    							zone.AddVisibleZone(mZoneList[visibleZoneId]);
    						}
    					}
    
    				}
    			}
    
    			return true;
    		}
    
    		public void Print()
    		{
    			for (int i = 0; i < mZoneLineCount; i++)
    			{
    				string str = "";
    				//遍历所有格子列
    				for (int j = 0; j < mZoneColumnCount; j++)
    				{
    					str += (i * mZoneColumnCount + j).ToString()+"	";
    				}
    				Debug.Print(str);
    			}
    		}
    
    		public void PrintZone(int i)
    		{
    			Debug.Print("[{0}]---------------------",i);
    			var zone = mZoneList[i];
    			string str = "";
    			foreach(var z in zone.VisibleZoneList)
    			{
    				
    				str+=z.mId.ToString()+"	";
    			}
    			Debug.Print(str);
    			Debug.Print("[{0}]---------------------",i);
    		}
    	}
    	class Program
    	{
    		static void Main(string[] args)
    		{
    
    			Scene scene = new Scene(5,7);
    			scene.InitZone();
    
    			scene.Print();
    
    			int oldId = 5;
    			int newId = 10;
    
    			Zone oldZone = scene.GetZone(oldId);
    			Zone newZone = scene.GetZone(newId);
    
    			/*
    			//比较计算应该删除我的zone
    			List<Zone> deleteMeZone = new List<Zone>();
    			foreach (var zone in oldZone.VisibleZoneList)
    			{
    				if (!newZone.VisibleZoneList.Contains(zone))
    				{
    					deleteMeZone.Add(zone);
    					Debug.Print(zone.mId.ToString());
    				}
    			}
    			Debug.Print("-----------");
    			//比较计算应该创建我的
    			List<Zone> createMeZone = new List<Zone>();
    			foreach (var zone in newZone.VisibleZoneList)
    			{
    				if (!oldZone.VisibleZoneList.Contains(zone))
    				{
    					createMeZone.Add(zone);
    					Debug.Print(zone.mId.ToString());
    				}
    			}
    			*/
    
    			scene.PrintZone(4);
    
    			scene.PrintZone(16);
    
    			scene.PrintZone(28);
    
    			scene.PrintZone(30);
    
    
    		}
    	}
    }
    

      

    //当角色位置发生改变

    protected void UpdateZone()
    		{
    			//安全检查
    			if (null == Scene || null == Zone)
    				return;
    
    			//获得我的zone id
    			int zoneId = Scene.Pos2ZoneId(mPosition.X, mPosition.Y);
    
    			Zone newZone = Scene.GetZone(zoneId);
    			if (null==newZone)
    			{
    				Logger.Fatal("[{0}] move out of scene[{1},{2}]", GetName(), GetPosition().X, GetPosition().Y);
    			}
    			//如果我的zone没变化
    			if (zoneId == Zone.Id) return;
    
    			//比较计算应该删除我的zone
    			List<Zone> deleteMeZone = new List<Zone>();
    			foreach (var zone in Zone.VisibleZoneList)
    			{
    				if (!newZone.VisibleZoneList.Contains(zone))
    				{
    					deleteMeZone.Add(zone);
    				}
    			}
    
    			//比较计算应该创建我的
    			List<Zone> createMeZone = new List<Zone>();
    			foreach (var zone in newZone.VisibleZoneList)
    			{
    				if (!Zone.VisibleZoneList.Contains(zone))
    				{
    					createMeZone.Add(zone);
    				}
    			}
    
    			//发包删除我
    			foreach(var zone in deleteMeZone)
    			{
    				zone.PushAction2AllPlayer((player)=>{
    					player.Proxy.DeleteObj(ObjId, (int)ReasonType.VisibilityChanged);
    				},ObjId);
    			}
    
    			//把该删除的通知我
    			if (GetObjType() == ObjType.PLAYER)
    			{
    				ObjPlayer player = this as ObjPlayer;
    				foreach (var zone in deleteMeZone)
    				{
    					zone.PushAction((obj) =>
    					{
    						if(obj!=this)
    						{
                                player.Proxy.DeleteObj(obj.ObjId, (int)ReasonType.VisibilityChanged);
    						}
    					});
    				}
    				
    			}
    
    			//发包创建我
    			CreateObjMsg msg2Other = new CreateObjMsg();
    			ObjData data = DumpObjData(ReasonType.VisibilityChanged);
    			msg2Other.Data.Add(data);
    			foreach (var zone in createMeZone)
    			{
    				zone.PushAction2AllPlayer((player) =>
    				{
    					if (IsVisibleTo(player))
    					{
    						player.Proxy.CreateObj(msg2Other);
    					}
    				}, ObjId);
    			}
    
    			//把周围所有人通知给我
    			if(GetObjType()==ObjType.PLAYER)
    			{
    				ObjPlayer player = this as ObjPlayer;
    
    				CreateObjMsg msg2Me = new CreateObjMsg();
    				foreach (var zone in createMeZone)
    				{
    					zone.PushAction((obj) =>
    					{
    						if(obj!=this)
    						{
    							if (obj.IsVisibleTo(this))
    							{
    								msg2Me.Data.Add(obj.DumpObjData(ReasonType.VisibilityChanged));
    							}
    						}
    					});
    				}
    				player.Proxy.CreateObj(msg2Me);
    			}
    			Zone.RemoveObj(this);
    			newZone.AddObj(this);
    			SetZone(newZone);
    		
    		}
    

      

  • 相关阅读:
    Central Contract无法传到ECC的排查工具
    直接采购在Core SRM与SRM PPS间的区别
    整理一下思路
    PR无法修改的几个原因
    MARCTRAME与MARCHTRAME
    Revision Level在PS中的决定
    Storage Location在物料分配时的选择逻辑
    如何正确删除WBS下的Planned Independent Requirement
    Open XML SDK 2.0
    Silverlight使用问题汇总一
  • 原文地址:https://www.cnblogs.com/mrblue/p/4652091.html
Copyright © 2011-2022 走看看