MMORPG大型游戏设计与开发(服务器 游戏场景 聊天管道和寻路器)
又快到双十一,又是不少同仁们出血的日子,首先希望大家玩的开心。我曾经想要仔细的剖析场景的的每个组件,就像这里的聊天管道与寻路器,但是仔细阅读别人代码的时候才发现元件虽小但是实现并不简单,因为有些东西还没有完全想明白我就暂时不说其具体的实现过程,但是我会保证这些文章在后面会不断更新,同时也希望对这方面有兴趣和经验的朋友们能够指正。聊天这个我们都知道,因为它几乎成了游戏或是生活中不可或缺的一部分,那么什么是寻路器?我想未必大家都知道什么是寻路器,不过我可以告诉大家的是你在游戏中自动寻路这个功能就是由该组件实现的。
一张截图

聊天管道
1、聊天数据
typedef struct chatitem_struct {
packet::Base *packet; //网络包指针
int32_t sourceid; //发起者ID
int32_t destid; //目标ID,队聊、场景聊、私聊、系统、自建聊天频道时目的对象ID。
} chatitem_t; //聊天单个数据
2、对象组成
1. 初始化(init)
初始化场景指针,分配聊天数据数组。
2. 心跳(heart beat)
心跳主要处理不同类型的聊天数据的分发。
3. 消息发送(send packet)
发送聊天数据包数据,并设置源ID和目标ID。
4. 消息接收(recv packet)
对应消息发送,读取网络数据包数据,读取源ID和目标ID。
寻路器
1、寻路数据
1. 地图数据
地图点的数据。
2. 导航图数据
大地图的数据,一般是地图寻路时需要打开的地图,需要提供其长宽的数据,如游戏截图中最上层的面板。
3. 格子的数据
场景中对象的存在一般是以格子作为单位,玩家角色也不例外。
4. 寻路点的数据
起始位置的X和Z坐标数据,目的位置的X和Z坐标数据。节点数据、寻路步奏数据等等。
2、对象实现
1. 析构函数(construct)
初始化当前的地图数据,以当前位置读取正确的坐标信息,并初始化寻路器数据对象。
2. 数据重置(reset)
重置开始的位置信息和结束的位置信息。
3. 路径查找(find path)
根据开始和结束位置信息,以及场景所有节点位置数据,并将所需寻路的节点数量保存到指定的指针中。
4. 路由打包(route pack)
打包AI所需经过的位置数据(注意玩家自身也有AI概念)。
5. 是否可到达(is can go)
该方法传入一个位置信息,返回是否可以到达该点,用在寻路时的判断,如不可达则不会去查询和生成寻路的数据。
算法(线性查找)
1、顺序查找
序查找实现简单,但是效率低,主要用在数据量不大以及效率要求不高的情况。
序查找可以利用顺序结构实现也可以利用链式结构实现。
code.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h> /**
* 顺序查找实现简单,但是效率低,主要用在数据量不大以及效率要求不高的情况。
* 顺序查找可以利用顺序结构实现也可以利用链式结构实现。
*/ #define SIZEMAX 100 typedef struct table_struct {
int32_t list[SIZEMAX];
int32_t length;
} table_t; //顺序查找,在顺序表中查找x,如果找到则返回元素在该表中的位置,否则返回0
int32_t seqsearch(table_t table, int32_t x);
//数组打印
int32_t displayarray(int32_t array[], int32_t length); int32_t main(int32_t argc, char *argv[]) {
table_t table = {{, , , , , , , , }, };
int32_t i, position, x;
printf("array members: ");
displayarray(table.list, table.length);
printf("please enter you want search member: ");
scanf("%d", &x);
position = seqsearch(table, x);
if (position) {
printf("member %d in array position is %d\n", x, position);
} else {
printf("member %d not find in array\n", x);
}
return ;
} int32_t seqsearch(table_t table, int32_t x) {
int32_t i = ;
while (i < table.length && table.list[i] != x) ++i;
if (table.list[i] == x) {
return i + ;
}
return ;
} int32_t displayarray(int32_t array[], int32_t length) {
int32_t i;
for (i = ; i < length; ++i)
printf("%4d", array[i]);
printf("\n");
}
result.

2、折半查找(二分查找)
折半查找又可以称作二分查找(原理和前面的折半插入排序一样)。
的效率虽然高于顺序查找的效率,但是它查找的序列必须是一个有序序列。
code.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h> /**
* 折半查找又可以称作二分查找
* 它的效率虽然高于顺序查找的效率,但是它查找的序列必须是一个有序序列。
*/
#define SIZEMAX 100 typedef struct table_struct {
int32_t list[SIZEMAX];
int32_t length;
} table_t; //在表中查找x,如果元素存在则返回元素所在位置,否则返回0
int32_t binarysearch(table_t table, int32_t x);
//数组打印
void displayarray(int32_t array[], int32_t length); int32_t main(int32_t argc, char *argv[]) {
table_t table = {{, , , , , , , , }, };
int32_t i, position, x;
printf("table list: ");
displayarray(table.list, table.length);
printf("please input a member you want search: ");
scanf("%d", &x);
position = binarysearch(table, x);
if (position) {
printf("member %d is in array position: %d\n", x, position);
} else {
printf("%d is not find in array\n", x);
}
return ;
} int32_t binarysearch(table_t table, int32_t x) {
int32_t low, high, middle;
low = , high = table.length - ; //设置待查找元素的下界和上界
while (low <= high) {
middle = (low + high) / ;
if (table.list[middle] == x) //如果找到元素,则返回该元素所在位置
return middle + ;
else if (table.list[middle] < x) //如果middle所在元素小于查找元素则向右移动low的位置
low = middle + ;
else if (table.list[middle] > x) //如果middle所在元素大于查找元素则向左移动high的位置
high = middle - ;
}
return ;
} void displayarray(int32_t array[], int32_t length) {
int32_t i;
for (i = ; i < length; ++i)
printf("%4d", array[i]);
printf("\n");
}
result.

3、分块查找
分块查找的索引表由主表和索引表构成,主表中的元素不一定有序,索引表中的元素一定有序。待查的元素序列比较多时,利用该算法可以快速确定待查找元素的大体位置,减少了比较次数。
code.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h> /**
* 分块查找的索引表由主表和索引表构成,主表中的元素不一定有序,索引表中的元素一定
* 有序。
* 当待查的元素序列比较多时,利用该算法可以快速确定待查找元素的大体位置,减少了比较次数。
*/
#define SIZEMAX 100
#define INDEXSIZE_MAX 20 typedef struct table_struct {
int32_t list[SIZEMAX];
int32_t length;
} table_t; //顺序表 typedef struct indextable_struct {
int32_t maxvalue;
int32_t index;
} indextable_t[INDEXSIZE_MAX]; //索引表 //在主表table中查找x元素,indextable为索引表,如果找到则返回位置否则返回0
int32_t seqindex_search(table_t table,
indextable_t indextable,
int32_t m,
int32_t x);
//数组打印
void displayarray(int32_t array[], int32_t length); int32_t main(int32_t argc, char *argv[]) {
table_t table = {{, , , , , , , , , ,
, , , , , , , , , }, };
indextable_t indextable = {{, }, {, }, {, }, {, }};
int32_t x, position, i;
printf("index table max value: \n");
for (i = ; i < ; ++i)
printf("%3d", indextable[i].maxvalue);
printf("\nlist array members: \n");
displayarray(table.list, table.length);
printf("input a number you want search: ");
scanf("%d", &x);
position = seqindex_search(table, indextable, , x);
if (position) {
printf("%d is a member of array, position: %d\n", x, position);
} else {
printf("%d is not a member of array\n");
}
return ;
} int32_t seqindex_search(table_t table,
indextable_t indextable,
int32_t m,
int32_t x) {
int32_t i, j;
int32_t b1;
for (i = ; i < m; ++i) { //通过索引表确定要查找元素在主表中的单元
if (indextable[i].maxvalue >= x) break;
}
if (i >= m) return ; //如果查找元素不再表table中,返回
j = indextable[i].index; //从第i个单元序号j开始查找元素x
if (i < m - ) { //b1为第j单元的长度
b1 = indextable[i + ].index - indextable[i].index;
} else {
b1 = table.length - indextable[i].index;
}
while (j < indextable[i].index + b1) {
if (table.list[j] == x) { //找到
return j + ;
}
++j;
}
return ;
} void displayarray(int32_t array[], int32_t length) {
int32_t i;
for (i = ; i < length; ++i)
printf("%4d", array[i]);
printf("\n");
}
result.

MMORPG大型游戏设计与开发(服务器 游戏场景 聊天管道和寻路器)的更多相关文章
- MMORPG大型游戏设计与开发(游戏服务器 游戏场景 概述 updated)
我们在玩游戏的时候,我们进入游戏后第一眼往往都是看到游戏世界中的场景,当然除了个别例外,因为那些游戏将游戏场景隐藏了起来,如文字游戏中的地点一样.既然我们接触了游戏世界的核心,那么作为核心的场景又包括 ...
- MMORPG大型游戏设计与开发(服务器 AI 概述)
游戏世界中我们拥有许多对象,常见的就是角色自身以及怪物和NPC,我们可以见到怪物和NPC拥有许多的行为,比如说怪物常常见到敌对的玩家就会攻击一样,又如一些NPC来游戏世界中走来走去,又有些怪物和NPC ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 动态场景与副本)
场景的内容讲解到今天算是暂时划上一个句号了,接下来为大家讲解的是AI部分(大型AI),如果有兴趣的朋友不妨持续关注这些文章,大家一起学习和进步.动态场景和副本是场景中特殊的类型,副本在这里想必已经是无 ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 核心详述)
核心这个词来的是多么的高深,可能我们也因为这个字眼望而却步,也就很难去掌握这部分的知识.之所以将核心放在最前面讲解,也可以看出它真的很重要,希望朋友们不会错过这个一直以来让大家不熟悉的知识,同我一起进 ...
- MMORPG大型游戏设计与开发(概述)updated
1.定义 MMORPG,是英文Massive(或Massively)Multiplayer Online Role-PlayingGame的缩写,即大型多人在线角色扮演游戏. 2.技术与知识 在这系列 ...
- MMORPG大型游戏设计与开发(客户端架构 part8 of vegine)
脚本模块是游戏设计中争论比较多的话题,那是因为作为脚本本身所带来的利弊.其实这都无关紧要,取舍是人必须学会的一项技能,如果你不会取舍那么就让趋势给你一个满意的答复.自从魔兽世界以及传奇(世界)问世以来 ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 地图和区域)
地图的数据以及区域的信息是场景的重要组成部分,这些数据同时存在客户端和服务器,而且都是由编辑器生成的.那么保存的文件数据结构是怎样的?一张3D的场景地图又是怎样处理这些数据的?同时告诉大家这里同样只是 ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 多线程)
多线程在随着cpu发展应用的是越来越多,游戏场景因为其在服务器所占的数据量与逻辑复杂度的原因必须依赖于它.为什么场景要采用多线程?场景的线程是怎样的?场景的线程又是如何创建的?场景的线程又是怎样管理的 ...
- MMORPG大型游戏设计与开发(服务器 AI 事件)
AI中的事件与场景中的事件大致相同,都是由特定的条件触发的.只不过AI的事件与其他事件不同的是,对于AI的事件往往是根据不同的AI类型,和动态的触发条件下才产生的.其实不管AI多么智能,它对应的触发条 ...
随机推荐
- [Access] C# 通过 COM 组件访问 Access 文件
说明: 1,采用 dynamic 调用 COM 组件,适用于 .NET 4.0 以上支持 dynamic 版本的才可以: 2,执行速度不敢恭维,只是因为要用于 Silverlight OOB 模式中才 ...
- 用C#读取相片(JPG图片)的EXIF信息的方法
引言:EXIF,是英文Exchangeable Image File{}#endregion#region 数据转换结构/// summary>/// 转换数据结构/// /summary> ...
- ABP之动态WebAPI(二)
HttpControllerDescriptor与HttpActionDescriptor HttpControllerDescriptor封装了某个HttpController类型的元数据,我们可以 ...
- JavaScript利用装饰模拟实现私有状态
在经典的面向对象编程中,经常需要将对象的某个状态封装或隐藏在对象内,只有通过对象的一幅幅和能访问这些状态,对外只暴露一些重要的状态变量可以直接读写. 我们可以通过将变量(或参数)装饰在一个构造函数内来 ...
- Combobox的使用
第一次写博客,只是对自己在工作中遇到的问题进行一次总结回顾,为以后有同样的错误有一个参考: 由于最近空余时间很少,只是零零散散的把平时记录的笔记搬到博客园而已,博客中可能出现一些低级错误,希望互相学习 ...
- JS时间戳格式化日期时间
由于mysql数据库里面存储时间存的是时间戳,取出来之后,JS要格式化一下显示.(李昌辉) 用的次数比较多,所以写了一个简单方法来转换: //时间戳转时间 function RiQi(sj) { va ...
- CSS3关于background-size属性
bachground-size属性就是定义背景图片的大小,其值有:auto , 像素值 , 百分比 , cover , contain . background-size: auto,默认值,以图 ...
- 翻译:常见问题——ABAP Development Tools for Eclipse
ABAP Development Tools for Eclipse(简称ADT)是一个基于Eclipse的全新ABAP IDE,这篇文档试图回答有关ADT的最重要的常见问题.这只是一个开始,如果你对 ...
- SharePoint 2013 Excel Services ECMAScript 示例之明日限行
前言:最近遇到一个“明日限行”的功能,北京的交通啊,这个不在今天讨论范围内,暂不吐槽,想想代码开发,还要写WebPart部署,很麻烦,而且部署服务器,需要领导审批,想绕过这个麻烦事儿,就想到客户端了, ...
- Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误
嵌套Fragment的使用及常见错误 嵌套Fragments (Nested Fragments), 是在Fragment内部又添加Fragment. 使用时, 主要要依靠宿主Fragment的 ge ...