一步一步开发Game服务器(四)地图线程

时隔这么久 才再一次的回归正题继续讲解游戏服务器开发。

开始讲解前有一个问题需要修正。之前讲的线程和定时器线程的时候是分开的。

但是真正地图线程与之前的线程模型是有区别的。

 

为什么会有区别呢?一个地图肯定有执行线程,但是每一个地图都有不同的时间任务。
比如检测玩家身上的buffer,检测玩家的状态值。这种情况下如何处理呢?很明显就需要定时器线程。

 我的处理方式是创建一个线程的时候根据需求创建对应的 timerthread

直接上代码其他不BB

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading;
  6 using System.Threading.Tasks;
  7 
  8 namespace Sz.ThreadPool
  9 {
 10     /// <summary>
 11     /// 线程模型
 12     /// </summary>    
 13     public class ThreadModel
 14     {
 15         /// <summary>
 16         /// 
 17         /// </summary>
 18         public bool IsStop = false;
 19         /// <summary>
 20         /// ID
 21         /// </summary>
 22         public int ID { get; private set; }
 23         /// <summary>
 24         /// 已分配的自定义线程静态ID
 25         /// </summary>
 26         public static int StaticID { get; private set; }
 27 
 28         string Name;
 29 
 30         /// <summary>
 31         /// 初始化线程模型,
 32         /// </summary>
 33         /// <param name="name"></param>
 34         public ThreadModel(String name)
 35             : this(name, 1)
 36         {
 37 
 38         }
 39 
 40         /// <summary>
 41         /// 初始化线程模型
 42         /// </summary>
 43         /// <param name="name">线程名称</param>
 44         /// <param name="count">线程数量</param>
 45         public ThreadModel(String name, Int32 count)
 46         {
 47             lock (typeof(ThreadModel))
 48             {
 49                 StaticID++;
 50                 ID = StaticID;
 51             }
 52             this.Name = name;
 53             if (count == 1)
 54             {
 55                 System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(Run));
 56                 thread.Name = "< " + name + "线程 >";                
 57                 thread.Start();
 58                 Logger.Info("初始化 " + thread.Name);
 59             }
 60             else
 61             {
 62                 for (int i = 0; i < count; i++)
 63                 {
 64                     System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(Run));
 65                     thread.Name = "< " + name + "_" + (i + 1) + "线程 >";                    
 66                     thread.Start();
 67                     Logger.Info("初始化 " + thread.Name);
 68                 }
 69             }
 70         }
 71 
 72         System.Threading.Thread threadTimer = null;
 73 
 74         /// <summary>
 75         /// 任务队列
 76         /// </summary>
 77         protected List<TaskModel> taskQueue = new List<TaskModel>();
 78         /// <summary>
 79         /// 任务队列
 80         /// </summary>
 81         private List<TimerTask> timerTaskQueue = new List<TimerTask>();
 82 
 83         /// <summary>
 84         /// 加入任务
 85         /// </summary>
 86         /// <param name="t"></param>
 87         public virtual void AddTask(TaskModel t)
 88         {
 89             lock (taskQueue)
 90             {
 91                 taskQueue.Add(t);
 92             }
 93             //防止线程正在阻塞时添加进入了新任务
 94             are.Set();
 95         }
 96 
 97         /// <summary>
 98         /// 加入任务
 99         /// </summary>
100         /// <param name="t"></param>
101         public void AddTimerTask(TimerTask t)
102         {
103             t.RunAttribute["lastactiontime"] = SzExtensions.CurrentTimeMillis();
104             if (t.IsStartAction)
105             {
106                 AddTask(t);
107             }
108             lock (timerTaskQueue)
109             {
110                 if (threadTimer == null)
111                 {
112                     threadTimer = new System.Threading.Thread(new System.Threading.ThreadStart(TimerRun));
113                     threadTimer.Name = "< " + this.Name + " - Timer线程 >";                    
114                     threadTimer.Start();
115                     Logger.Info("初始化 " + threadTimer.Name);
116                 }
117                 timerTaskQueue.Add(t);
118             }
119             timerAre.Set();
120         }
121 
122         /// <summary>
123         /// 通知一个或多个正在等待的线程已发生事件
124         /// </summary>
125         protected ManualResetEvent are = new ManualResetEvent(false);
126 
127         /// <summary>
128         /// 通知一个或多个正在等待的线程已发生事件
129         /// </summary>
130         protected ManualResetEvent timerAre = new ManualResetEvent(true);
131 
132         /// <summary>
133         /// 线程处理器
134         /// </summary>
135         protected virtual void Run()
136         {
137             while (!this.IsStop)
138             {
139                 while ((taskQueue.Count > 0))
140                 {
141                     TaskModel task = null;
142                     lock (taskQueue)
143                     {
144                         if (taskQueue.Count > 0)
145                         {
146                             task = taskQueue[0];
147                             taskQueue.RemoveAt(0);
148                         }
149                         else { break; }
150                     }
151 
152                     /* 执行任务 */
153                     //r.setSubmitTimeL();
154                     long submitTime = SzExtensions.CurrentTimeMillis();
155                     try
156                     {
157                         task.Run();
158                     }
159                     catch (Exception e)
160                     {
161                         Logger.Error(Thread.CurrentThread.Name + " 执行任务:" + task.ToString() + " 遇到错误", e);
162                         continue;
163                     }
164                     long timeL1 = SzExtensions.CurrentTimeMillis() - submitTime;
165                     long timeL2 = SzExtensions.CurrentTimeMillis() - task.GetSubmitTime();
166                     if (timeL1 < 100) { }
167                     else if (timeL1 <= 200L) { Logger.Debug(Thread.CurrentThread.Name + " 完成了任务:" + task.ToString() + " 执行耗时:" + timeL1 + " 提交耗时:" + timeL2); }
168                     else if (timeL1 <= 1000L) { Logger.Info(Thread.CurrentThread.Name + " 长时间执行 完成任务:" + task.ToString() + " “考虑”任务脚本逻辑 耗时:" + timeL1 + " 提交耗时:" + timeL2); }
169                     else if (timeL1 <= 4000L) { Logger.Error(Thread.CurrentThread.Name + " 超长时间执行完成 任务:" + task.ToString() + " “检查”任务脚本逻辑 耗时:" + timeL1 + " 提交耗时:" + timeL2); }
170                     else
171                     {
172                         Logger.Error(Thread.CurrentThread.Name + " 超长时间执行完成 任务:" + task.ToString() + " “考虑是否应该删除”任务脚本 耗时:" + timeL1 + " 提交耗时:" + timeL2);
173                     }
174                     task = null;
175                 }
176                 are.Reset();
177                 //队列为空等待200毫秒继续
178                 are.WaitOne(200);
179             }
180             Console.WriteLine(DateTime.Now.NowString() + " " + Thread.CurrentThread.Name + " Destroying");
181         }
182 
183         /// <summary>
184         /// 定时器线程处理器
185         /// </summary>
186         protected virtual void TimerRun()
187         {
188             ///无限循环执行函数器
189             while (!this.IsStop)
190             {
191                 if (timerTaskQueue.Count > 0)
192                 {
193                     IEnumerable<TimerTask> collections = null;
194                     lock (timerTaskQueue)
195                     {
196                         collections = new List<TimerTask>(timerTaskQueue);
197                     }
198                     foreach (TimerTask timerEvent in collections)
199                     {
200                         int execCount = timerEvent.RunAttribute.GetintValue("Execcount");
201                         long lastTime = timerEvent.RunAttribute.GetlongValue("LastExecTime");
202                         long nowTime = SzExtensions.CurrentTimeMillis();
203                         if (nowTime > timerEvent.StartTime //是否满足开始时间
204                                 && (nowTime - timerEvent.GetSubmitTime() > timerEvent.IntervalTime)//提交以后是否满足了间隔时间
205                                 && (timerEvent.EndTime <= 0 || nowTime < timerEvent.EndTime) //判断结束时间
206                                 && (nowTime - lastTime >= timerEvent.IntervalTime))//判断上次执行到目前是否满足间隔时间
207                         {
208                             //提交执行
209                             this.AddTask(timerEvent);
210                             //记录
211                             execCount++;
212                             timerEvent.RunAttribute["Execcount"] = execCount;
213                             timerEvent.RunAttribute["LastExecTime"] = nowTime;
214                         }
215                         nowTime = SzExtensions.CurrentTimeMillis();
216                         //判断删除条件
217                         if ((timerEvent.EndTime > 0 && nowTime < timerEvent.EndTime)
218                                 || (timerEvent.ActionCount > 0 && timerEvent.ActionCount <= execCount))
219                         {
220                             timerTaskQueue.Remove(timerEvent);
221                         }
222                     }
223                     timerAre.Reset();
224                     timerAre.WaitOne(5);
225                 }
226                 else
227                 {
228                     timerAre.Reset();
229                     //队列为空等待200毫秒继续
230                     timerAre.WaitOne(200);
231                 }
232             }
233             Console.WriteLine(DateTime.Now.NowString() + "Thread:<" + Thread.CurrentThread.Name + "> Destroying");
234         }
235     }
236 }
View Code

当我线程里面第一次添加定时器任务的时候加触发定时器线程的初始化。

先看看效果

 

地图运作方式怎么样的呢?

来一张图片看看

在正常情况下一个地图需要这些事情。然后大部分事情是需要定时器任务处理的,只有客户端交互通信是不需要定时器任务处理。

封装地图信息类

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 using Sz.MMO.GameServer.IMapScripts;
  7 using Sz.MMO.GameServer.TimerMap;
  8 using Sz.MMO.GameServer.TimerMonster;
  9 
 10 
 11 /**
 12  * 
 13  * @author 失足程序员
 14  * @Blog http://www.cnblogs.com/ty408/
 15  * @mail 492794628@qq.com
 16  * @phone 13882122019
 17  * 
 18  */
 19 namespace Sz.MMO.GameServer.Structs.Map
 20 {
 21     /// <summary>
 22     /// 
 23     /// </summary>
 24     public class MapInfo<TPlayer, TNpc, TMonster, TDropGoods> : IEnterMapMonsterScript, IEnterMapNpcScript, IEnterMapPlayerScript, IEnterMapDropGoodsScript
 25     {
 26         /// <summary>
 27         /// 为跨服设计的服务器id
 28         /// </summary>
 29         public int ServerID { get; set; }
 30         /// <summary>
 31         /// 地图模板id
 32         /// </summary>
 33         public int MapModelID { get; set; }
 34         /// <summary>
 35         /// 地图id
 36         /// </summary>
 37         public long MapID { get; set; }
 38 
 39         /// <summary>
 40         /// 地图分线处理
 41         /// </summary>
 42         Dictionary<int, MapLineInfo<TPlayer, TNpc, TMonster, TDropGoods>> mapLineInfos = new Dictionary<int, MapLineInfo<TPlayer, TNpc, TMonster, TDropGoods>>();
 43 
 44         public MapInfo(string name, int mapModelId, int lineCount = 1)
 45         {
 46 
 47             this.MapID = SzExtensions.GetId();
 48             this.MapModelID = mapModelId;
 49             Logger.Debug("开始初始化地图: " + name + " 地图ID:" + MapID);
 50 
 51             for (int i = 1; i <= lineCount; i++)
 52             {
 53                 MapLineInfo<TPlayer, TNpc, TMonster, TDropGoods> lineInfo = new MapLineInfo<TPlayer, TNpc, TMonster, TDropGoods>(name + "-" + i + "线");
 54 
 55                 mapLineInfos[i] = lineInfo;
 56             }
 57             Logger.Debug("初始化地图: " + name + " 地图ID:" + MapID + " 结束");
 58         }
 59 
 60     }
 61 
 62     #region 地图分线 class MapLineInfo<TPlayer, TNpc, TMonster, TDropGoods> : IEnterMapMonsterScript, IEnterMapNpcScript, IEnterMapPlayerScript, IEnterMapDropGoodsScript
 63     /// <summary>
 64     /// 地图分线
 65     /// </summary>
 66     /// <typeparam name="TPlayer"></typeparam>
 67     /// <typeparam name="TNpc"></typeparam>
 68     /// <typeparam name="TMonster"></typeparam>
 69     /// <typeparam name="TDropGoods"></typeparam>
 70     class MapLineInfo<TPlayer, TNpc, TMonster, TDropGoods> : IEnterMapMonsterScript, IEnterMapNpcScript, IEnterMapPlayerScript, IEnterMapDropGoodsScript
 71     {
 72         public MapThread MapServer { get; set; }
 73 
 74         public int ServerID { get; set; }
 75 
 76         public int LineID { get; set; }
 77 
 78         public int MapModelID { get; set; }
 79 
 80         public long MapID { get; set; }
 81 
 82         public MapLineInfo(string name)
 83         {
 84             Players = new List<TPlayer>();
 85             Monsters = new List<TMonster>();
 86             Npcs = new List<TNpc>();
 87             DropGoodss = new List<TDropGoods>();
 88             MapServer = new Structs.Map.MapThread(name);
 89         }
 90 
 91         /// <summary>
 92         /// 地图玩家
 93         /// </summary>
 94         public List<TPlayer> Players { get; set; }
 95 
 96         /// <summary>
 97         /// 地图npc
 98         /// </summary>
 99         public List<TNpc> Npcs { get; set; }
100 
101         /// <summary>
102         /// 地图怪物
103         /// </summary>
104         public List<TMonster> Monsters { get; set; }
105 
106         /// <summary>
107         /// 地图掉落物
108         /// </summary>
109         public List<TDropGoods> DropGoodss { get; set; }
110     }
111     #endregion
112 }
View Code
   Structs.Map.MapInfo<Player, Npc, Monster, Drop> map = new Structs.Map.MapInfo<Player, Npc, Monster, Drop>("新手村", 101, 2);

 



这样就创建了一张地图。我们创建的新手村有两条线。也就是两个线程

这样只是创建地图容器和地图线程而已。

如何添加各个定时器呢?

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 using Sz.MMO.GameServer.IMapScripts;
  7 
  8 
  9 /**
 10  * 
 11  * @author 失足程序员
 12  * @Blog http://www.cnblogs.com/ty408/
 13  * @mail 492794628@qq.com
 14  * @phone 13882122019
 15  * 
 16  */
 17 namespace Sz.MMO.GameServer.TimerMap
 18 {
 19     /// <summary>
 20     /// 
 21     /// </summary>
 22     public class MapHeartTimer : ThreadPool.TimerTask
 23     {
 24 
 25         int serverID, lineID, mapModelID;
 26         long mapID;
 27 
 28         /// <summary>
 29         /// 指定1秒执行一次
 30         /// </summary>
 31         public MapHeartTimer(int serverID, int lineID, long mapID, int mapModelID)
 32             : base(1000 * 10)
 33         {
 34             this.serverID = serverID;
 35             this.lineID = lineID;
 36             this.mapID = mapID;
 37             this.mapModelID = mapModelID;
 38         }
 39 
 40         /// <summary>
 41         /// 
 42         /// </summary>
 43         public override void Run()
 44         {
 45             
 46             Logger.Debug("我是地图心跳检查器 执行线程:" + System.Threading.Thread.CurrentThread.Name);
 47             Logger.Debug("我是地图心跳检查器 检查玩家是否需要复活,回血,状态");
 48             //var scripts = Sz.ScriptPool.ScriptManager.Instance.GetInstances<IMapHeartTimerScript>();
 49             //foreach (var item in scripts)
 50             //{
 51             //    item.Run(serverID, lineID, mapID, mapModelID);
 52             //}
 53         }
 54 
 55     }
 56 }
 57 
 58 
 59 
 60 
 61 
 62 using System;
 63 using System.Collections.Generic;
 64 using System.Linq;
 65 using System.Text;
 66 using System.Threading.Tasks;
 67 using Sz.MMO.GameServer.IMonsterScripts;
 68 
 69 
 70 /**
 71  * 
 72  * @author 失足程序员
 73  * @Blog http://www.cnblogs.com/ty408/
 74  * @mail 492794628@qq.com
 75  * @phone 13882122019
 76  * 
 77  */
 78 namespace Sz.MMO.GameServer.TimerMonster
 79 {
 80     /// <summary>
 81     /// 
 82     /// </summary>
 83     public class MonsterHeartTimer: ThreadPool.TimerTask
 84     {
 85 
 86         int serverID, lineID, mapModelID;
 87         long mapID;
 88 
 89         /// <summary>
 90         /// 指定1秒执行一次
 91         /// </summary>
 92         public MonsterHeartTimer(int serverID, int lineID, long mapID, int mapModelID)
 93             : base(1000 * 10)
 94         {
 95             this.serverID = serverID;
 96             this.lineID = lineID;
 97             this.mapID = mapID;
 98             this.mapModelID = mapModelID;
 99         }
100 
101         /// <summary>
102         /// 
103         /// </summary>
104         public override void Run()
105         {            
106             Logger.Debug("怪物心跳检查器 执行线程:" + System.Threading.Thread.CurrentThread.Name);
107             Logger.Debug("怪物心跳检查器 检查怪物是否需要复活,需要回血,是否回跑");
108             //var scripts = Sz.ScriptPool.ScriptManager.Instance.GetInstances<IMonsterHeartTimerScript>();
109             //foreach (var item in scripts)
110             //{
111             //    item.Run(serverID, lineID, mapID, mapModelID);
112             //}
113         }
114     }
115 }
116 
117 
118 
119 using System;
120 using System.Collections.Generic;
121 using System.Linq;
122 using System.Text;
123 using System.Threading.Tasks;
124 
125 
126 /**
127  * 
128  * @author 失足程序员
129  * @Blog http://www.cnblogs.com/ty408/
130  * @mail 492794628@qq.com
131  * @phone 13882122019
132  * 
133  */
134 namespace Sz.MMO.GameServer.TimerMonster
135 {
136     /// <summary>
137     /// 
138     /// </summary>
139     public class MonsterRunTimer: ThreadPool.TimerTask
140     {
141 
142         int serverID, lineID, mapModelID;
143         long mapID;
144 
145         /// <summary>
146         /// 指定1秒执行一次
147         /// </summary>
148         public MonsterRunTimer(int serverID, int lineID, long mapID, int mapModelID)
149             : base(1000 * 5)
150         {
151             this.serverID = serverID;
152             this.lineID = lineID;
153             this.mapID = mapID;
154             this.mapModelID = mapModelID;
155         }
156 
157         /// <summary>
158         /// 
159         /// </summary>
160         public override void Run()
161         {            
162             Logger.Debug("怪物移动定时器任务 执行线程:" + System.Threading.Thread.CurrentThread.Name);
163             Logger.Debug("怪物移动定时器任务 怪物随机移动和回跑");
164             //var scripts = Sz.ScriptPool.ScriptManager.Instance.GetInstances<IMonsterHeartTimerScript>();
165             //foreach (var item in scripts)
166             //{
167             //    item.Run(serverID, lineID, mapID, mapModelID);
168             //}
169         }
170     }
171 }
View Code

 

就在初始化地图线程的时候加入定时器任务

 

 

 1         public MapInfo(string name, int mapModelId, int lineCount = 1)
 2         {
 3 
 4             this.MapID = SzExtensions.GetId();
 5             this.MapModelID = mapModelId;
 6             Logger.Debug("开始初始化地图: " + name + " 地图ID:" + MapID);
 7 
 8             for (int i = 1; i <= lineCount; i++)
 9             {
10                 MapLineInfo<TPlayer, TNpc, TMonster, TDropGoods> lineInfo = new MapLineInfo<TPlayer, TNpc, TMonster, TDropGoods>(name + "-" + i + "线");
11                 //添加地图心跳检测器
12                 lineInfo.MapServer.AddTimerTask(new MapHeartTimer(ServerID, i, MapID, MapModelID));
13                 //添加怪物移动定时器
14                 lineInfo.MapServer.AddTimerTask(new MonsterRunTimer(ServerID, i, MapID, MapModelID));
15                 //添加怪物心跳检测器
16                 lineInfo.MapServer.AddTimerTask(new MonsterHeartTimer(ServerID, i, MapID, MapModelID));
17 
18                 mapLineInfos[i] = lineInfo;
19             }
20             Logger.Debug("初始化地图: " + name + " 地图ID:" + MapID + " 结束");
21         }
其实所有的任务定时器处理都是交给了timer线程,timer线程只负责查看该定时当前是否需要执行。
而具体的任务执行移交到线程执行器。线程执行器是按照队列方式执行。保证了timer线程只是一个简单的循环处理而不至于卡死
同样也保证了在同一张地图里面各个单元参数的线程安全性。

来看看效果。

为了方便我们看清楚一点,我把地图线程改为以一条线。

这样就完成了各个定时器在规定时间内处理自己的事情。

需要注意的是这里只是简单的模拟的一个地图处理各种事情,最终都是由一个线程处理的。那么肯定有人要问了。
你一个线程处理这些事情能忙得过来嘛?
有两点需要注意
1,你的每一个任务处理处理耗时是多久,换句话说你可以理解为你一秒钟能处理多少个任务。
2,你的地图能容纳多少怪物,多少玩家,多少掉落物?换句话说也就是你设计的复杂度间接限制了你的地图有多少场景对象。

那么还有什么需要注意的呢?

其实地图最大的消耗在于寻路。高性能的寻路算法和人性化寻路算法一直是大神研究的对象,我也只能是借鉴他们的了。

这一章我只是简单的阐述了地图运行和任务等划分和构成已经任务处理流程。

接下来我会继续讲解游戏服务器编程,一步一步的剖析。

文路不是很清晰。希望大家不要见怪。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、网狐荣耀版短信验证开发流程说明 现在的很多游戏,都有短信验证登录的功能,特别是国内比较火的网狐棋牌系统,有的甚至直接短信验证码为登录密码,这确实是一个好的思路,保证了密码不被盗。但是,短信验证怎么实现呢?很多开发者有时会出现暂时的迷茫。下面我就把大概的思路告诉大家。一、申请短信通道,国内的短信通道很多,不同的通道速度不一样,我们在申请时要一个基本原则就是速度要快,基本上要发送即接收了,客户不可能等的。国内调查发现,客户等网页打开的时间是最长不超过5秒,短信接收的时间最长不超过10秒。当然,特殊的短信例外,比如银行确认短信等涉及财产安全的短信;二、手机客户端或PC客户端开发出相应的短信验证功能,进行手机号码的接收,接收到手机号码后,直接发送服务器端,这里当然不能客户端集成直接发,那就会被别人利用了。服务器端发送短信。客户接收到短信后就可以进行验证。 二、网狐荣耀版棋牌机器人配置完了不进游戏不上桌 在网狐荣耀版机器人配置中经常遇到机器人配置完了不进游戏,不上桌。这个问题一般是几方面的问题造成的。 一、你的这款游戏是否支持机器人,支持的话就服务器端会有相应的机器人组件。 二、支持机器人,但是机器人组件没在服务器端目录,或没有。 三、这个游戏是否配置了机器人,有时可能是配置错了,好好的详细再查一下吧。 、机器人数量不够,已经用尽。 五、游戏机器人没有开启。 基本上就这些原因了,每个都要细细的查,这样才能发现问题。 可以咨询q-q457189 三、网狐荣耀版手机端在复制文本时提示“复制内容非法”的解决办法 在网狐荣耀版开发调试过程中,复制文本时,提示“复制非法内容”,开始吓一跳,没有什么非法内容啊?也没有禁词,也没有国家不允许的内容。最后通过程序查看,原来是平台的问题。换安卓、苹果系统就好了。 、最新出炉的网狐荣耀版机器人添加视频教程 最新出炉的网狐荣耀版机器人添加视频教程,包括机器人的导入,机器人的分配,机器人的配置,房间的配置等。全方位的讲解了网狐荣耀版机器人的管理添加过程。可以联系我获取下载地址。Q-Q457189 五、网狐荣耀版安卓端的签名与打包 第一、打开ADT,选择file-import,加载荣耀版安卓项目。 第二,右键项目,选择export,进入下图界面,选择android,然后再选择Export Android Application,然后选择下一步,这里默认,再进行下一步。 第三步,这里选择Create new keystore,Location选择存储路径,Passowrd输入签名密码,Confirm确认密码。然后进行下一步步,填写好各个相关信息,注意密码那里和上个页面的一致。其它随便。然后下一步,选择打包APK文件的存储路径。 第五步,点击finish等待程序签名与APK的生成,结束。 六、网狐荣耀版游戏启动时出现“正在初始化组件”启动失败 【 2017-11-10 08:35:33 】[ 游戏 ] 房间参数加载成功 【 2017-11-10 08:35:35 】正在初始化组件... 【 2017-11-10 08:36:41 】服务启动失败 【 2017-11-10 08:36:41 】服务停止成功 这样的问题有两个原因造成 一、开发库是否正确,不正确,重新生成开发库。 二、游戏kindid设置是否正确,不正确修改。 这两个问题解决了,问题就迎刃而解了。 祝你好运。 七、网狐荣耀版"定时器异常:TimerID=2“错误 在网狐荣耀版进行机器人操作或其它操作时,经常会出现"定时器异常:TimerID=2“错误,这个错误怎么处理呢? 这里提示其实已经很明白了,就是定时器错误。 一和运行库有关系,二和操作有关。 八、网狐荣耀版棋牌游戏机器人的添加 在棋牌运营过程中,没有机器人开始是很难运行的,没有人气,那么,网狐荣耀版棋牌游戏怎么添加机器人呢?下面简单说明 加机器人首先要有一些机器人的名字,这些名字可以自己搜集,也可以用网上别人搜集的,比如Q-Q名。然后用脚本一键导入。 用户信息导入后,就可以用机器人工具进行房间的机器人分配了。 九、eclipse加载荣耀版时红叉an outline is not available报错的处理 很多时候这些错误不是程序问题造成,而是环境问题造成。这个主要是第三方的类库与cocos2d-x的支持文件没有加载的原因造成,加载了就可以正常运行了。 十、网狐荣耀版手机端分享时出现“由于不支持的分享类型,无法分享到微信“的解决办法 去腾讯开放平台申请账号,审核通过后,在开放平台添加相应信息,就可以正常分享了。 十一、网狐荣耀版vs生成解决方案时出现“出现未能写入日志,请求的操作无法在使用用户映射区域打开的文件上执行“错误 一、定位文件,看是不是只读。 二、删除文件试一下,看看是不是文件被占用,如果删除不了,就是被占用,可以查是哪个程序占用,不行重启服务器试一下。 三、是不是路径有问题。 十二、网狐荣耀版房卡游戏在手机客户端不出现房卡房间 最近,有个别网友找我,的架设网狐荣耀版游戏时,服务器端开了房卡房间,但是在手机端没有房间显示,更不用谈进入房间了。经查,程序没有问题,相同的源码,相同的环境配置,就是不出现房卡房间,最后我也是无语了。我告诉他,你人品有问题。但是问题还是得查出原因。经过详细的分析研究,最后是他电脑CPU的问题。费了十天的时间,经历了太多的误解与磨难。真不容易。 十三、网狐荣耀版android编译时出现“未找到工程,Android 目标平台版本应该大于或等于 21” 这个是因为sdk版本设置问题造成的,设置正确相应的sdk版本,就可以了。 十、网狐荣耀版微信登录没有反应失败的解决办法 网狐荣耀版的登录方式有了很大的变化,三种形式:账号登录、游客登陆与微信登陆。在开发与使用网狐棋牌荣耀版时账号登陆与游客登录时基本上都没有什么问题,但是在使用微信登录时会遇到点微信登录没有反应,有反应后进不去等等问题。遇到这样的情况,是因为腾讯开放平台配置问题,注册开放平台,进行客户端相应参数的设置就可以了。 十五、在网狐荣耀版添加房卡游戏时,经常有网友遇到进房卡房间弹出到大厅登录界面 这个问题经常有网友咨询,经过调试,最后确定是开发库不配套的问题。经过更新,重新生成开发库,问题解决。 十六、网狐荣耀版斗地主第三个人进入开始时弹出 网狐荣耀版斗地主第三个人进入开始时弹出,这样的问题经常有网友遇到。 经过问题分析,代码查看,是开发库的问题,解决了开发库问题,就正常了。 十七、网狐荣耀版李奎劈鱼游戏,捕鱼游戏提示“非法组件的解决办法” 在使用网狐荣耀版时,捕鱼进入游戏时提示非法组件,如下图,这个是因为未授权的原因,只要授权就可以了。授权的方法可以联系 十八、网狐荣耀版大厅版本更新出现“下载失败,CODE 7,是否重试?”的错误 网狐荣耀版,有一些客户反应,在大厅版本更新后,客户端下载更新出现了,“下载失败,CODE 7,是否重试?”的错误。这个是一配置的错误问题造成的,修改后台更新配置。 十九、网狐荣耀版棋牌中心服务器显示“服务启动失败”的原因 网狐荣耀版棋牌,在启动中心服务器时,显示“服务启动失败”,如下图。这是因为开发库不配套的问题产生的。更新了开发库,问题解决。 二十、网狐荣耀版手机端登录提示“网络错误:5”解决办法 这是因为服务器端授权问题、内核问题或是手机端的配置问题造成的,请看内核是否为248K的内核,并检查网络模块是否为34.7K的网络模块,如果没有问题请检查手机端相应位置的配置信息。配置一定要细心做好。如果还不行可以 二十一、网狐荣耀版房卡房间分享给好友,好友点击后空白,或没反应的解决办法 最近总遇到网友反应,网狐荣耀版房卡游戏,在创建房间后,邀请好友等操作后。好友点击分享链接没反应或是空白,或是出错。这样的问题,在进行代码修改和相应的设置后,问题解决。 二十二、网狐荣耀版启动游戏时提示“相应的游戏服务组件信息不存在,房间创建失败” 这个是因为游戏的kindid与创建的游戏的kindid不一致造成的,修改游戏的kindid为你的游戏的kindid就可以了。 二十三、网狐荣耀版出现在sys.servers中找不到服务器'rytreasuredblink'。请验证指定的服务器名称是否正确 这个问题是因为数据库是附加的,脚本代码里面的创建链接服务器脚本没有执行,执行一下就好了。Q-Q:457189 二十、网狐荣耀版系统模块编译出现fatal error c1083:无法打开包含文件“d3d9.h” :no such fil 这个是因为没有把directx sdk添加到项目引用中。加入directx sdk的引用就可以了。Q-Q:457189 二十五、网狐荣耀版苹果端ipa打包流程说明 在网狐荣耀版系统开发,游戏开发,界面cocos和lua开发等过程后,要进行发布和打包。pc端与安卓端相对简单,苹果端的修改、发布与打包成了多数开发者的一个主要问题。下面就说说这个苹果打包的基本过程。 一、环境准备 macos电脑一台,安装xcodes开发工作,同时安装证书服务器与相关软件环境。 二、系统修改 xcodes打开项目工程,进行开发者的配置与发布选项的配置,进行游戏名称与版本号修改等,进行编译,发布等。这里面的游戏开发者最好是企业开发者账号,因为这样就不用上传到苹果商店了。可以随便分发。 三、导出ipa文件,上传到fir.im,蒲公英之类的网站,客户下载就行了。 Q-Q:457189 二十六、网狐荣耀版游戏服务器出现"MDM_GF_GAME 游戏命令返回 false" 网狐荣耀版游戏服务器出现"MDM_GF_GAME 游戏命令返回 false",这是因为游戏客户端数据与服务器端不匹配造成的,修改客户端后,问题解决。 二十七、网狐荣耀版棋牌游戏输赢控制设置 在游戏使用过程中,输赢控制是必不可少的,那怎么怎么进行游戏控制呢?下面简单简介。 一、控制账号的注册。 二、控制客户端的生成。 三、进行控制。 就这三步即可实现控制。 二十八、网狐荣耀版手机端与pc端热更新的配置 手机端的热更新是,首先设置好版本号,然后生成手机端,生成后,把生成的文件全部上传到网站更新目录里面,然后管理后台配置更新目录与版本,就可以了。pc端的更新是上传到相应目录,然后生成更新版本信息。 二十九、网狐荣耀最新版视频教程 网狐荣耀最新版视频教程,从开始的基础操作,架设,到最后的安卓修改编译,苹果修改编译等。 网狐荣耀版教程一认识网狐荣耀版 网狐荣耀版教程二环境搭建 网狐荣耀版教程三数据库的附加和导入 网狐荣耀版教程网站管理后,台和代,理的搭建 网狐荣耀版教程五PC端系统的修改和编译 网狐荣耀版教程六服务器端的搭建 网狐荣耀版教程七PC客户端的打包 网狐荣耀版教程八子游戏的添加 网狐荣耀版教程九安卓端的签名 网狐荣耀版教程十苹果环境的搭建 网狐荣耀版教程十一苹果端ios的修改和打包 网狐荣耀版教程十二安卓手机端的修改和编译 网狐荣耀版教程十三手机端热更新的配置 在系统的使用与运营过程中,会有很多问题,这些教程只要认真学习,都会迎刃而解。当然在解决的过程中也要动脑。 实在解决不了,可以互相沟通Q-Q:457189 三十、网狐荣耀版服务器端启动出现“您的服务器组件没有得到合法授权,服务器将会以受限模式运行” 这个就是因为内核组件没有破解,然后认证没有通过。建议去网狐公司购买正版和正版授权。Q-Q:457189 三十一、网狐荣耀版棋牌教程之一开发环境搭建 一、安装JDK1.8,下载jdk1.8,然后双击安装,下一步直到安装完成,安装的时候记住安装目录,我的全部默认安装,目录为C:\Program Files\Java\Jdk1.8。安装完成后,进行环境变量的配置。系统变量中进行JAVA_HOME、CLASSPATH、Path三个变量的配置,有的编辑,没有的新建。新建JAVA_HOME对应C:\Program Files\Java\Jdk1.8、新建CLASSPATH对应.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar、编辑Path的最后加上;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin。最后打开CMD窗口进行测试是否安装成功。 二、把winrar加入环境变量,使winrar可以在命令行下直接运行。;C:\Program Files\WinRAR 三、安装cocos,这里我们使用的是cocos2d-x 3.10,3.10版本,Cocos2d-x与cocos整合升级为Cocos引擎,下载后是exe程序,双击直接安装,很简单。 、下载自动提示补全词典,我还下载了cocos2dx-3.10-api.lua,把下载的词典放到,我的文档下面的BabeLua\Completion文件夹中,再进入lua项目,输入代码时就有相应的提示了。 五、安装python-2.7.10,双击安装,下一步直到完成,在安装时选择一下目录,我安装到了c盘的python27目录。安装完后进行环境变量的配置。在系统变量的path最后加上;C:\Python27,pyghon安装完成。打开CMD窗口进行测试。 六、安装ant 1.9.6,下载ant 1.9.6,解压,这里我们解压到C盘的ant196目录。然后配置环境变量,没有的项创建,有的项编辑。 ANT_HOME C:\ant196 path C:\ant196\bin classpath C:\ant196\lib 七、安装adt,下载ADT后解压,我们这里解压到C盘的adt-bundle-windows-x86-20140624目录。 运行eclipse,打开help,install new software,名称输入adt_plugin,adt插件的站点为:https://dl-ssl.google.com/android/eclipse/ 将“com.android.ide.eclipse.ndk_23.0.2.1259578.jar”复制到"C:\adt-bundle-windows-x86-20140624\eclipse\plugins\com.android.ide.eclipse.ndk_23.0.2.1259578.jar" 添加环境变量 ANDROID_SDK_ROOT 为:C:\adt-bundle-windows-x86-20140624\sdk; 八、安装NDK 把android-ndk-r10d-windows-x86_64复制到要安装的目录,双击android-ndk-r10d-windows-x86_64进行解压。这里我们解压后的目录为c盘的android-ndk-r10d目录。 启动"C:\adt-bundle-windows-x86-20140624\eclipse\eclipse.exe" 选择菜单栏上的[Window->Perferences->Android->NDK]设置 NDK Loaction 为C:\android-ndk-r10d; 添加环境变量 NDK_ROOT 为:C:\android-ndk-r10d 在环境变量 PATH 下追加 :%NDK_ROOT%; 至此,网狐荣耀版开发环境基本搭建完成。 q-q457189 三十二、网狐荣耀版进入手机客户端显示“获取服务器列表失败,是否重试?” 这个问题有原因有几个,一可能是服务器端的IP连接设置有问题;二是游戏更新有问题。 Q-Q457189 三十三、网狐荣耀版或其它安卓项目出现Application cannot be exported due to the erro 网狐荣耀版或其它安卓项目出现Application cannot be exported due to the error(s) below.错误的处理方法 此错误的意思是你的项目存在编译错误,您必须处理了全部错误才可以进行导出操作。 三十、网狐荣耀版更新工具更新文件创建失败怎么处理? 三十五、网狐荣耀版大厅里进游戏一闪一闪的进不去,正在检查怎么处理? 三十六、网狐荣耀版服务端启动出现“请注意,您正在使用未被授权的组件,无法启动服务器,请联系深圳网狐科技有限公司!”怎么处理? 三十七、网狐荣耀版开发环境怎么配置? 三十八、网狐荣耀版手机端热更新怎么配置? 三十九、网狐荣耀版进入手机客户端显示“获取服务器列表失败,是否重试?”怎么处理? 十、网狐荣耀版手机端生成时出现MakeMD5List.exe 应用程序错误的解决办法 这是因为动态链接库版本不对,更新就好了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值