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的基本概述以及组成,作为与场景模块中核心一样重要的地位,基础部分的设计 ...
随机推荐
- .NET Task揭秘(一)
Task为.NET提供了基于任务的异步模式,它不是线程,它运行在线程池的线程上.本着开源的精神, 本文以解读基于.NET4.5 Task源码的方式来揭秘Task的实现原理. Task的创建 Tas ...
- 推荐几个Web前端开发实用的Chrome插件
越来越多的前端开发人员喜欢在Chrome里开发调试代码,Chrome有许多优秀的插件可以帮助前端开发人员极大的提高工作效率.尤其Chrome本身是可以登录的,登录后你所有的插件都会自动同步到每一个登录 ...
- ASP.Net Core MVC6 RC2 启动过程分析[偏源码分析]
入口程序 如果做过Web之外开发的人,应该记得这个是标准的Console或者Winform的入口.为什么会这样呢? .NET Web Development and Tools Blog ASP.NE ...
- 【NopCommerce源码架构学习-二】单例模式实现代码分析
单例模式是是常用经典十几种设计模式中最简单的..NET中单例模式的实现也有很多种方式.下面我来介绍一下NopCommerce中单例模式实现. 我之前的文章就分析了一下nop中EngineContext ...
- python 优矿自动化交易
一.进入官网,打开notebook 自己新建 notebook 二.在代码中编写自己的交易策略 https://uqer.io/help/faqApi/#account相关属性 在帮助文档中可以找到 ...
- 配置Java SSL 访问网站证书
最近在开发 Java 访问 Azure ServiceBus 时遇到SSL证书问题,导致JAVA报错,不能正常访问,报错信息如下: javax.net.ssl.SSLException: Connec ...
- ABP 初探 之User、Role、Permission数据库设计 (EntityFramework 继承的另一种使用方法)
最近群里(134710707)的朋友都在讨论ABP源码,我把最近学习的内容记录下来,同时也分享给大家,希望正在研究ABP源码的朋友有一定帮助. 上篇介绍ABP的多语言,本篇主要介绍权限的数据库设计,用 ...
- 3、ASP.NET MVC入门到精通——Entity Framework增删改查
这里我接上讲Entity Framework入门.从网上下载Northwind数据库,新建一个控制台程序,然后重新添加一个ado.net实体数据模型. EF中操作数据库的"网关"( ...
- Effective c++读书笔记
1.视C++为一个语言联邦 C.object-oriented C++.template C++.STL 2.尽可能使用const: 1)关键字const出现的星号左边,表示被指物事常 ...
- border-radius结合transition的一个小应用(动画)
<head lang="en"> <meta charset="UTF-8"> <title></title> ...