MMORPG大型游戏设计与开发(服务器 游戏场景 多线程)
多线程在随着cpu发展应用的是越来越多,游戏场景因为其在服务器所占的数据量与逻辑复杂度的原因必须依赖于它。为什么场景要采用多线程?场景的线程是怎样的?场景的线程又是如何创建的?场景的线程又是怎样管理的?在这里同时对可以指正错误的朋友们说声谢谢,虽然是小错误,也希望大家能够勇于纠正这些错误。
游戏截图
采用理由
上面的两张截图分别在不同的场景,试想一下如果一个线程只能先处理其中一张图的数据,后果会怎么样?
单线程往往需要等待,就好像我们到银行窗口办理业务的时候,以前的时候很多网点只有一个窗口,所以我们不得不排队等候,然而随着时代的进步银行的窗口随着业务的开展越来越多,更多的业务员使得我们省去了排队的烦恼。而游戏场景在游戏中处理的逻辑是最为复杂的,特别是一些大场景的数据那更是多不胜数,程序处理逻辑数据需要时间,在单线程里面对复杂的逻辑就需要等待不少的时间,数据和逻辑越复杂其等待的时间就会越长,你想如果我们在玩游戏的时候在A场景的时候,B场景因为要等待A场景的逻辑处理完成后才能够处理其场景的数据,也就是说A场景的人先走动完成后,B场景的玩家才能走动。
为了让所有场景的数据都能在较短的时间内处理,我们就需要更多的处理者来帮忙,也就是我们拥有更多的线程来处理,如果只有一个线程处理N个场景当然很慢,如果有M个场景同时处理N个场景速度则会大大提高,这就是我们之所以选择多线程的原因。而且一个线程所能承受的场景数量,往往是跟场景的数据量大小以及复杂度有关。
场景多线程
1、线程管理器(manager)
用于添加场景线程并初始化线程数据。
2、线程池(pool)
多个线程数据的集合管理。
3、线程分配(thread)
这个世界上最理想的是有足够的资源,就像这里一样每个线程负责一个场景就是最理想的,因为这样效率是最高的。线程越多消耗的CPU自然成正比例的增加,就好像地球上的资源一样,没有办法完全的满足需求一样,这样我们就必须想办法进行资源共享,一个线程负责多个场景。记得小时候的劳动课一样,有时候工具不够的情况下,老师往往会将同学们分成几组,每组共享那些工具,但是有的时候一个工具分了很多人使用,超过了负荷的时候就达不到老师的要求(比如老师要求规定时间内每个人都要使用工具多少次,因为人数太多甚至有的人工具都碰不到)。
线程的负载主要表现在程序执行的快慢和效率上,如果效率明显很低影响到了正常的工作,我们就不得不想办法提升效率。最直接影响场景线程的负载的便是负责场景数量,所以场景线程有规定的场景上限。
一般流程
场景管理器创建所有场景(scene manager)->线程池对象初始化(thread pool)->线程管理器分配场景线程(thread manager)->场景线程管理器运行所有线程(thread manager)
算法(交换排序)
1、冒泡排序(bubble sort)
交换相邻的两个元素,将最大的元素逐渐移动到最后,如果数组大小为N,则N次之后数组则变为有序的数组。泡排序算法主要用于排序元素较少且时间要求不太高的场合。这里进行了算法改进:增加一个标记,如果已经没有需要交换的元素则后面不需再排序。
code.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h> /**
* 交换相邻的两个元素,将最大的元素逐渐移动到最后,如果数组大小为N,则N次之后数组则变为有序的数组
* 冒泡排序算法主要用于排序元素较少且时间要求不太高的场合
* 算法改进:增加一个标记,如果已经没有需要交换的元素则后面不需再排序
*/ void printarray(int32_t array[], int32_t length);
void bubblesort(int32_t array[], int32_t length); int32_t main(int32_t argc, char *argv[]) {
int32_t array[] = {, , , , , , , , , };
int32_t length = sizeof(array) / sizeof(array[]);
bubblesort(array, length);
return ;
} void printarray(int32_t array[], int32_t length) {
int32_t i;
for (i = ; i < length; ++i)
printf("%4d", array[i]);
printf("\n");
} void bubblesort(int32_t array[], int32_t length) {
int32_t i, j;
int32_t temp;
uint8_t flag = ;
for (i = ; i < length && == flag; ++i) {
flag = ;
for (j = ; j < length - i; ++j) {
if (array[j] > array[j + ]) {
temp = array[j];
array[j] = array[j + ];
array[j + ] = temp;
flag = ;
}
}
printf("the %d times result: ", i);
printarray(array, length);
}
}
result.
2、快速排序(quick sort)
快速排序算法是冒泡排序算法的改进,但是实现却比冒泡复杂很多,它主要针对大数据排序,果对时间要求不是很高可以使用直接插入排序或者冒泡排序。其特点是排序的时间效率比较高,并且在特别大的数据量时十分明显。同希尔算法一样,快速排序是一种不太稳定的算法,和其实现的原理有关。
code.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h> /**
* 快速排序算法是冒泡排序算法的改进,但是实现却比冒泡复杂很多,它主要针对大数据排序,
* 如果对时间要求不是很高可以使用直接插入排序或者冒泡排序
* 其特点是排序的时间效率比较高,并且在特别大的数据量时十分明显。
* 同希尔算法一样,快速排序是一种不太稳定的算法,和其实现的原理有关。
*/ //数组打印
void displayarray(int32_t array[], int32_t length);
//输出每次划分的结果
void _displayarray(int32_t array[], int32_t length, int32_t pivot, int32_t count);
//快速排序核心实现
void _quicksort(int32_t array[], int32_t length, int32_t low, int32_t high);
//快速排序函数,对数组的元素进行排序
void quicksort(int32_t array[], int32_t length);
//对素组array[low...high]的元素进行一趟排序,使枢轴前面的元素小于枢轴元素,
//枢轴后面的元素大于等于枢轴元素,并返回枢轴元素
int32_t partition(int32_t array[], int32_t low, int32_t high); int32_t main(int32_t argc, char *argv[]) {
int32_t array[] = {, , , , , , , , , , };
int32_t length = sizeof(array) / sizeof(array[]);
printf("before sort: ");
displayarray(array, length);
quicksort(array, length);
printf("after sort: ");
displayarray(array, length);
return ;
} void displayarray(int32_t array[], int32_t length) {
int32_t i;
for (i = ; i < length; ++i)
printf("%4d", array[i]);
printf("\n");
} void _displayarray(int32_t array[],
int32_t length,
int32_t pivot,
int32_t count) {
int32_t i;
printf("the %d times result: [", count);
for (i = ; i < pivot; ++i)
printf("%-4d", array[i]);
printf("]");
printf("%3d ", array[pivot]);
printf("[");
for (i = pivot + ; i < length; ++i)
printf("%-4d", array[i]);
printf("]");
printf("\n");
} void _quicksort(int32_t array[], int32_t length, int32_t low, int32_t high) {
int32_t pivot;
static int32_t count = ;
if (low < high) { //如果元素序列的长度大于1
pivot = partition(array, low, high); //将待排序序列array[low...high]划分为两部分
_displayarray(array, length, pivot, count); //输出每次划分的结果
++count;
_quicksort(array, length, low, pivot - ); //对左边的子表进行递归排序,pivot是枢轴位置
_quicksort(array, length, pivot + , high); //对右边的子表进行递归排序
}
} void quicksort(int32_t array[], int32_t length) {
_quicksort(array, length, , length - );
} int32_t partition(int32_t array[], int32_t low, int32_t high) {
int32_t temp, pivot;
pivot = array[low]; //将第一个元素作为枢轴元素
temp = array[low];
while (low < high) { //从表的两端交替的向中间扫描
while (low < high && array[high] >= pivot) //从表的末端向前扫描
--high;
if (low < high) { //将当前high指向的元素保存在low位置
array[low] = array[high];
++low;
}
while (low < high && array[low] <= pivot) //从表的开始向后扫描
++low;
if (low < high) { //将当前low指向的元素保存在high位置
array[high] = array[low];
--high;
}
array[low] = temp;
}
return low;
}
result.
MMORPG大型游戏设计与开发(服务器 游戏场景 多线程)的更多相关文章
- MMORPG大型游戏设计与开发(游戏服务器 游戏场景 概述 updated)
我们在玩游戏的时候,我们进入游戏后第一眼往往都是看到游戏世界中的场景,当然除了个别例外,因为那些游戏将游戏场景隐藏了起来,如文字游戏中的地点一样.既然我们接触了游戏世界的核心,那么作为核心的场景又包括 ...
- MMORPG大型游戏设计与开发(服务器 AI 概述)
游戏世界中我们拥有许多对象,常见的就是角色自身以及怪物和NPC,我们可以见到怪物和NPC拥有许多的行为,比如说怪物常常见到敌对的玩家就会攻击一样,又如一些NPC来游戏世界中走来走去,又有些怪物和NPC ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 动态场景与副本)
场景的内容讲解到今天算是暂时划上一个句号了,接下来为大家讲解的是AI部分(大型AI),如果有兴趣的朋友不妨持续关注这些文章,大家一起学习和进步.动态场景和副本是场景中特殊的类型,副本在这里想必已经是无 ...
- MMORPG大型游戏设计与开发(概述)updated
1.定义 MMORPG,是英文Massive(或Massively)Multiplayer Online Role-PlayingGame的缩写,即大型多人在线角色扮演游戏. 2.技术与知识 在这系列 ...
- MMORPG大型游戏设计与开发(客户端架构 part8 of vegine)
脚本模块是游戏设计中争论比较多的话题,那是因为作为脚本本身所带来的利弊.其实这都无关紧要,取舍是人必须学会的一项技能,如果你不会取舍那么就让趋势给你一个满意的答复.自从魔兽世界以及传奇(世界)问世以来 ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 地图和区域)
地图的数据以及区域的信息是场景的重要组成部分,这些数据同时存在客户端和服务器,而且都是由编辑器生成的.那么保存的文件数据结构是怎样的?一张3D的场景地图又是怎样处理这些数据的?同时告诉大家这里同样只是 ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 核心详述)
核心这个词来的是多么的高深,可能我们也因为这个字眼望而却步,也就很难去掌握这部分的知识.之所以将核心放在最前面讲解,也可以看出它真的很重要,希望朋友们不会错过这个一直以来让大家不熟悉的知识,同我一起进 ...
- MMORPG大型游戏设计与开发(服务器 AI 事件)
AI中的事件与场景中的事件大致相同,都是由特定的条件触发的.只不过AI的事件与其他事件不同的是,对于AI的事件往往是根据不同的AI类型,和动态的触发条件下才产生的.其实不管AI多么智能,它对应的触发条 ...
- MMORPG大型游戏设计与开发(服务器 AI 基础接口)
一个模块都往往需要统一的接口支持,特别是对于非常大型的模块,基础结构的统一性非常重要,它往往决定了其扩展对象的通用性.昨天说了AI的基本概述以及组成,作为与场景模块中核心一样重要的地位,基础部分的设计 ...
随机推荐
- 记住 MVC里用formcollection接收form表单传来的值,表单属性必须有name为健!
记住 MVC里用formcollection接收form表单传来的值,input属性必须有name为健! 调了一晚上!! 写个日志记下!!
- 微信JSApi支付~集成到MVC环境后的最后一个坑(网上没有这种解决方案)
返回目录 大叔第一人 之前写了关于微信的坑<微信JSApi支付~坑和如何填坑>,今天将微信的jsapi支付封装到了MVC环境里,当然也出现了一些新的坑,如支付参数应该是Json对象而不是J ...
- php导入excel表格
我们做网站的时候经常要用到excel导入和导出的功能,我们通常的做法是用phpexcel工具包来完成,具体方法如下: html代码: <form action="{:U('Mall/u ...
- 【nodejs笔记2】认识express框架
app.js:启动文件,或者说入口文件package.json:存储着工程的信息及模块依赖,当在 dependencies 中添加依赖的模块时,运行 npm install,npm 会检查当前目录下的 ...
- How do I see all foreign keys to a table or column?
down voteaccepted For a Table: SELECT TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME, ...
- javaweb学习总结(三十八)——事务
一.事务的概念 事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功. 例如:A——B转帐,对应于如下两条sql语句 update from account set mone ...
- PHP运行环境,服务器相关配置
1.在DOS命令窗口输入 mysql -hlocalhost -uroot -p回车 进入mysql数据库, 其中-h表示服务器名,localhost表示本地:-u为数据库用户名,root是mysql ...
- 回溯法求n的全排列
代码如下: #include <iostream> #include <algorithm> #include <stdio.h> #include <cst ...
- [javaSE] 注解-自定义注解
注解的分类: 源码注解 编译时注解 JDK的@Override 运行时注解 Spring的@Autowired 自定义注解的语法要求 ① 使用@interface关键字定义注解 ② 成员以无参无异常方 ...
- DecoratorPattern(装饰器模式)
/** * 装饰者模式 * @author TMAC-J * 总的来说,装饰者模式就是继承的应用 */ public class DecoratorPattern { interface Beans{ ...