糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 多人即时战斗游戏服务端系列[2]--90坦克Online游戏对象介绍以及渲染机制

多人即时战斗游戏服务端系列[2]--90坦克Online游戏对象介绍以及渲染机制

时间:2020-07-15 10:25:26

相关推荐

多人即时战斗游戏服务端系列[2]--90坦克Online游戏对象介绍以及渲染机制

先上类图,略大,点击此处放大:

1.先说下方接口

1.1场景物品接口 ISceneObject : OpLog.IOpItem, IStackPoolObject

全部场景对象的基本接口,包含类型定义,通用渲染接口,所在场景,子对象树,尺寸,坐标等..

1.2 游戏场景接口 IScene : ISceneObject

继承于基本场景接口,拥有加入对象,对象列表,获取相邻对象,等其它逻辑.

1.3 Buff基类IBuff

buff表现,拥有持续时间,加入/删除/移动/开火/渲染/被击中时触发事件

1.4 爆裂物接口IHitSceneObject

假设须要造成伤害/或者破坏物体,都须要先拥有一个爆裂物,爆裂物会检測爆裂范围内的接口,然后逐个进行碰撞.

1.5 可移动物品接口 IMoveSceneObject

拥有方向,速度,以及射程,继承此接口对象,当你设置一个速度,在每帧渲染时,都会移动,直到收到停止或最大可移动距离

1.6 可加入Buff对象ICanBuffSceneObject

继承此接口物品可加入/移除buff,并受ibuff事件触发.

1.7 可使用装置接口(主动/被动技能)IDevice

分为2类一般,发射一个子弹,或者加入一个buff,或者两者都有

1.8 地图上可获取道具接口IItem

仅參与碰撞,被碰撞后会对碰撞对象加入一个触发buff.

2.然后是上方buff,全部的对象改动功能大部分都是buff触发无敌/武器升级/无法移动/减速/回血等..

3武器 装置和buff的关系

3.1全部的buff有个持续时间,有一到两个可选參数.

3.2 全部武器都会发射子弹,全部子弹都会创建一个爆裂物,爆裂物能够对碰撞对象产生伤害和加入buff

3.3 全部子弹/爆裂物都有碰撞列表,仅会对有效的目标进行伤害和加入buff

4 游戏世界GameWorld

4.1每场游戏都是一个游戏世界

4.2每一个游戏时间包括一个场景

4.3每帧这个世界会进行活动.通过fpstimer

4.4 不同的游戏世界有不同的游戏模式,通过继承GameWorld

5.渲染

5.1 基类实现,检查是否有子对象,然后进行子对象渲染(调用一次 ,对象有渲染等级,也就是渲染优先级,有些每帧渲染,有些每5帧渲染以此类推)

/// <summary>/// 渲染/// </summary>/// <param name="ms"></param>public virtual void Render(int ms, int lv){if (SubObjects != null && SubObjects.Count > 0){Assert.IsNull(SubObjects, "SubObjects");foreach (var sceneObject in SubObjects){sceneObject.Render(ms, lv);}}}

5.2 场景渲染方法 (管理加入物体和移除物体)

/// <summary>/// 渲染全部物体/// </summary>/// <param name="ms"></param>public override void Render(int ms, int lv){base.Render(ms, lv);Assert.IsNull(SceneObjects, "SceneObjects");#if TESTvar sw = new System.Diagnostics.Stopwatch();sw.Start();#endif//加入延迟对象if (DelaySceneObjects.Count > 0){lock (DelaySceneObjects){var removeList = new List<DelaySceneObject>();foreach (var sceneObject in DelaySceneObjects){if (sceneObject != null && sceneObject.ActiveTime < CurrentTimeGetter.Now){removeList.Add(sceneObject);if (OnAddSceneObject == null || OnAddSceneObject(sceneObject.SceneObject))AddObject(sceneObject.SceneObject);}}foreach (var delaySceneObject in removeList){DelaySceneObjects.Remove(delaySceneObject);}}#if TESTif (sw.ElapsedMilliseconds > 20)logger.Debug("DelaySceneObjects Add:" + sw.ElapsedMilliseconds);#endif}var list = RenderList;if (OthersLv.Count > 0){list = RenderList.Where(r => !(r is OtherSceneObject) ||(r as OtherSceneObject).Lv <= 0 ||lv % (r as OtherSceneObject).Lv == 0).ToList();}foreach (var sceneObject in list){//Assert.IsNull(sceneObject, "sceneObject");if (sceneObject != null && sceneObject.Hp > 0){sceneObject.Render(ms, lv);}else{SceneObjects.Remove(sceneObject);}}}

5.3 游戏场景渲染

/// <summary>/// 渲染事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void timer_Elapsed(object sender, FpsTimer.FpsElapsedEventArgs e){if (ThreadNum == 0){ThreadNum = System.Threading.Thread.CurrentThread.ManagedThreadId;}else{if (System.Threading.Thread.CurrentThread.ManagedThreadId != ThreadNum){#if DEBUGSystem.Diagnostics.Debugger.Break();#endif}}#if !TESTtry{#endifif (!IsStart){if ((CurrentTimeGetter.Now - StartTime).TotalMilliseconds > TankConfigs.AutoStartGameSleep){IsStart = true;Statues = GameStatues.Start;CurrentScene.AddMessage(new Message(){Type = MessageType.RoundStart,Content = CurrentTimeGetter.Now + ":回合開始:" + OpId});}}if (!IsStart){return;}#if DEBUGlong lastms = sw.ElapsedMilliseconds;#endifMs += (int) e.ElapsedMilliseconds;if (CurrentTimeGetter.Now.Second != lastReaderTime.Second){if (Math.Abs((Avg - TankConfigs.RenderFps)) > TankConfigs.RenderFps/5 || Math.Abs((Ms - 1000)) > 200)logger.Warn("[" + OpId + "]Fps:" + Avg + " MS:" + Ms);Ms = Avg = 0;}lastReaderTime = CurrentTimeGetter.Now;LeftMs += (int)e.ElapsedMilliseconds;this.BeforeRender();for (int i = 0; i < (LeftMs / (TankConfigs.RenderTimer)); i++){Avg++;if (CurrentScene != null){CurrentScene.Render((int)(TankConfigs.RenderTimer), LoopSeed++ % 100);}LeftMs -= (int) (TankConfigs.RenderTimer);}if (LeftMs >= TankConfigs.RenderTimer){Avg++;if (CurrentScene != null){CurrentScene.Render((int)(LeftMs), LoopSeed++ % 100);}LeftMs = 0;}this.AfterRender();if (Time <= 0){Close();}#if DEBUGif (sw.ElapsedMilliseconds - lastms > TankConfigs.RenderTimer*5){logger.Warn("渲染时间过长:" + (sw.ElapsedMilliseconds - lastms));}#endif#if !TEST}catch (Exception ex){logger.ErrorException(ex, "渲染出错!");ErrorCount++;if (ErrorCount >= TankConfigs.MaxReaderErrorCount){RoundEnd(0);}}#endif}

保证每秒能渲染到设定的帧数60fps,过快或者过慢,过慢进行渲染补偿(连续渲染,过快进行跳过,等待下秒)

这里并不採用每一个世界一个线程的渲染方式,而是使用线程池,相应一个线程渲染几个特定的游戏世界,用于避开一些多线程锁操作.

6.玩家操作流程

6.1 玩家命令会进入相应操作的坦克队列

/// <summary>/// 开火/// </summary>/// <param name="index">武器序号</param>/// <param name="arg">投掷參数1-100</param>public void Fire(int index = 0, int arg = 0){if (CheckStatues()){if (Tank.Devices.Count > index){Tank.EnqueueCmd(new Tank.TankCmd(Tank.TankCmd.OpCmd.Fire, index, arg));}}}

6.2 坦克会在渲染时运行队列中的命令

public override void Render(int ms, int lv){while (true){TankCmd cmd = null;Cmds.TryDequeue(out cmd);if (cmd != null){switch (cmd.Cmd){case TankCmd.OpCmd.Fire:FireOnWeapon(Devices[(int) cmd.Args[0]], (int) cmd.Args[1]);break;case TankCmd.OpCmd.Move:MoveOn((Direction) cmd.Args[0]);break;case TankCmd.OpCmd.StopMove:Block();break;}}else{break;}}base.Render(ms,lv);//检查装置CDforeach (var device in Devices){device.Render(ms);}//Buff渲染触发foreach (var buff in Buffs){buff.OnReader(this, ms);}//移除时间已经到了的buffforeach (var buff in Buffs){if (CurrentTimeGetter.Now > buff.EndTime){buff.OnBuffRemove(this);}}}

如果觉得《多人即时战斗游戏服务端系列[2]--90坦克Online游戏对象介绍以及渲染机制》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。