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

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);}}}

转载于:https://www.cnblogs.com/jhcelue/p/6918648.html

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

  1. 手机游戏服务端怎么找到_做手机游戏14年,我们有这样一些心得和你聊

    来源:见实(ID:jianshishijie) 排版:杂芜 对于微信小游戏,小奥互动副总裁李娅不想错过这个潜在的机会,但也一直避免自己被市场风云莫测的变化轻易干扰.毕竟,从Java时代几十K的像素风游 ...

  2. 手机游戏服务端怎么找到_抖音游戏直播怎么开启?如何把手机或者电脑投屏到抖音直播?...

    抖音上有各种各样的视频,今天来讲一下抖音怎么开游戏直播.相信很多人都在抖音上刷到过游戏的视频,比如王者荣耀.绝地求生等游戏类型的视频在抖音上都是很好涨粉的,所以如果能够结合开通游戏直播,那么不光涨粉更 ...

  3. java做h5小游戏服务端_神藏西游H5游戏源码服务端+客户端+搭建教程

    源码预览 源码介绍 教程如下: 1.cd / 把下载好的文件传到服务器根目录下面 2.打开Xshell 安装java 输入 sh sd 回车 输入1 回车 3.安装宝塔 输入 sh sd 回车 输入2 ...

  4. 百万在线:大型游戏服务端开发

    进入手游时代,服务端技术也在向前演进.现代游戏服务端既要承载数以万计的在线玩家,又要适应快速变化的市场需求,因此,如何设计合适的架构就成了重中之重.服务端技术并不简单,作为服务端新人,全面掌握服务端技 ...

  5. 谈谈一只菜鸟转行Erlang游戏服务端的经历(希望大佬指导,也希望我的经历能给一些还未毕业的同学或者正在迷茫自己工作内容的同学一些感触)

    入行半年Erlang游戏服务端的心得体验 个人经历 转方向后的工作经历 工作中遇到的问题和处理 一些游戏服务端开发的体验和想法 最后谈谈自己现在面临的问题 第一次发文章,主要想谈谈自己近半年来的心路历 ...

  6. 用Python架设大型多人在线游戏服务端

    用Python架设大型多人在线游戏服务端 用Python架设大型多人在线游戏服务端应用领域非常广泛,包括战网的暗黑破坏神,社区的QQ宠物等.该文档将帮助大家回顾2011届Python介绍的架构的缺陷以 ...

  7. Java游戏服务端开发系列文章

    已经好久没有更新自己的学习状态.或许是工作太忙吧,生活被工作羁绊,无法抽身.最近因为某些事情的原因,工作上有点充裕的时间来分享自己的一点小小经验.因为毕竟我也是一个混迹职场几年了 虽然天资不咋地,但是 ...

  8. java游戏服务端实现

     java游戏服务端实现 一个多人在线的棋牌类网络游戏的项目临近尾声,我参与了该项目的整个设计流程,并且完成了90%的核心代码.关于这个项目,有很多地方值得聊一聊.本系列不打算把这个项目将得多么详 ...

  9. 游戏服务端开发之基础概念扫盲篇

    13年毕业后,做了一年多外包web开发,因为受不了在客户现场工作的氛围,愤然辞职.转行做了一名手游服务端开发. 在广州,据我所知,选择java作为服务端开发语言的公司大概有37互娱,百田,银汉,易娱, ...

最新文章

  1. NLP研究索引神器,3000+代码库,一键查找论文、GitHub库
  2. Citrix各系列产品安装光盘资源下载链接
  3. Foundation框架: 11.NSDate的基本认识和使用
  4. sql case 语句
  5. 1万属性,100亿数据,每秒10万吞吐,架构如何设计?
  6. java reader_Java Reader ready()方法与示例
  7. psutil模块安装指南(win与linux)
  8. 传熊猫直播进入破产清算 3月18日关闭服务器
  9. 决策树CART算法讲解
  10. 日语+AI语音黑科技,早道开启小语种AI智能时代!
  11. 服务器里的文件链接地址怎么写,服务器里的文件链接地址怎么写
  12. 浏览器了解(一)浏览器大概流程
  13. pandas corr()函数
  14. MDK5如何生成bin文件
  15. CNN结构:色彩特征提取-色彩属性HSV空间(色彩冷暖初始)
  16. HTML meta 标签的使用方式总结(本文总结17中使用方式)
  17. PocketPC常用程序和设置打开命令参数列表
  18. 本命年第三季度阶段反思
  19. 微信支付分开通了!对飙芝麻信用分!开通与查看攻略!
  20. 联力L216装机心得

热门文章

  1. python怎么设置文本框大小_如何在Python中更改Tkinter文本框的宽度和高度?
  2. 异型烟分拣 机器人_智能物流装备咨询规划,仓储自动化分拣系统,立体库智能多穿车,物流集成商解决方案,AGV堆垛机穿梭车,兰剑智能科技...
  3. 我的CAD操作方式(使用的cad2014和 ObjectARX 基础操作来实现的)
  4. Gradle学习(二十)——多项目构建详解
  5. oracle查视图字段类型,oracle,如何查看视图结构,获得视图中的字段名称、字段类型、字段长度等。...
  6. 个人收藏之 - 一些有趣网站
  7. 关于白色PDF太刺眼的解决办法(一键“夜间模式”)
  8. java中sql语句换行_java中sql语句快速处理
  9. js获取当前时间戳(10位)
  10. python写rest服务_Python 如何创建一个简单的REST接口