今天第星期天,知识是永远是学习不完的,所以今天这部分算比较轻松,同时也希望大家会有一个好的周末。场景事件即场景的回调,和别的事件一样是在特定的条件下产生的,前面也介绍过场景的各种事件,今天详细的说一说这些事件的具体作用。

游戏截图

场景事件

一个完整的对象一般都拥有事件,至于什么是事件在这里就不多解释了。在场景中的事件在天龙/武侠世界中的事件包括场景初始化、场景定时器、场景退出、玩家进入场景、角色升级、角色死亡、角色重生、场景通知、任务接受检查、NPC对话默认事件、NPC事件列表事件。

1、场景初始化(scene init)

场景初始化事件,负责副本场景的数据维护、负责副本定时器的开启、负责城市入口的挂接、调用脚本初始化函数。

2、场景定时器(scene timer)

负责定时器数据的处理,一般会调用到脚本的相应函数。

3、场景退出(scene quit)

场景退出一般是清理数据的作用,首先调用脚本的场景退出函数,然后移除所有对象。移除的对象包括玩家、怪物、宠物、操作台、掉落包。

4、玩家进入(player enter)

一个玩家进入场景产生的事件,一般调用脚本函数处理该事件。

5、玩家升级(player level up)

玩家升级后的回调,试想一下玩家升级后会有哪些数据的改变?场景中有哪些数据需要更新?是不是这里的玩家升级事件也就包括了其他数据的改变?

6、玩家死亡(player death)

玩家死亡一般伴随着许多数据的改变,如常见的金钱掉落,物品掉落等等,还有玩家死亡可能会触发任务状态的改变,或一个剧情等等。

7、玩家复活(player relive)

玩家的复活事件,是不是玩家复活的时候常见的数据直接在逻辑中就实现了,还是要放到事件函数中?我们这里常说的事件函数一般都是指调用脚本,调用脚本其实为了能够频繁的改动数据。

8、玩家断线(player disconnect)

断线是一个痛苦的事情,特别是在我们玩的正开心的时候,但是怎么也比不过一些实在的数据处理的时候,如天龙八部中离线事件中把玩家交易的完全处理放到了这里。

9、场景通知(scene notify)

一开始一听这个事件的时候我也曾觉得很迷茫,但是看了具体代码的时候才知道在游戏中是为副本场景来服务的,只有当副本已经初始化完成才会收到该消息用来传送玩家到副本中。

10、任务接受检查事件(mission accept check)

要接受一个任务会有条件的,如人物等级的限制、所在场景、事件限制等等。

11、NPC默认对话框事件(npc default dialog)

如果是可以交互的NPC则会有对话框来表现这种交互,如果还有默认的操作则将默认操作的选项显示出来。

12、NPC默认事件列表(npc default event list)

默认事件列表是指NPC默认的一些事件,这些事件在经过该回调正确的检查之后才显示正确的选项。

算法(归并和基数排序)

1、归并排序

并排序算法实现复杂,因为二路归并算法需要的临时空间较大,所以常常用在外部序中。(其核心的思想为将两个或两个以上的元素有序序列合并为一个有序序列)

并算法是一种稳定的排序算法。

code.

#include <stdio.h>
#include <stdint.h>
#include <malloc.h>
#include <inttypes.h> /**
* 归并排序算法实现复杂,因为二路归并算法需要的临时空间较大,所以常常用在外部
* 排序中。(其核心的思想为将两个或两个以上的元素有序序列合并为一个有序序列)
* 归并算法是一种稳定的排序算法。
*/ //将source数组中的元素复制到dest数组中,其中,length为长度,first是目标数组的起始位置
void copyarray(int32_t source[], int32_t dest[], int32_t length, int32_t first);
//归并排序
void mergesort(int32_t array[], int32_t left, int32_t right);
//合并两个子序列中的元素
void merge(int32_t array[], int32_t left, int32_t right);
//数组打印
void displayarray(int32_t array[], int32_t length); int32_t main(int32_t argc, char *argv[]) {
int32_t array[] = {, , , , , , , , };
int32_t length = sizeof(array) / sizeof(array[]);
printf("before sort: ");
displayarray(array, length);
mergesort(array, , length - );
printf("after sort: ");
displayarray(array, length);
return ;
} void copyarray(int32_t source[], int32_t dest[], int32_t length, int32_t first) {
int32_t i, j = first;
for (i = ; i < length; ++i) {
dest[j] = source[i];
++j;
}
} void mergesort(int32_t array[], int32_t left, int32_t right) {
int32_t i;
if (left < right) {
i = (left + right) / ;
mergesort(array, left, i);
mergesort(array, i + , right);
merge(array, left, right);
}
} void merge(int32_t array[], int32_t left, int32_t right) {
int32_t begin1, begin2, middle, k = , length;
int32_t *pointer = NULL;
begin1 = left;
middle = (left + right) / ;
begin2 = middle + ;
length = right - left + ;
pointer = (int32_t *)malloc(length * sizeof(int32_t));
if (NULL == pointer) return;
while (begin1 <= middle && begin2 <= right) {
if (array[begin1] < array[begin2]) {
pointer[k++] = array[begin1++];
} else {
pointer[k++] = array[begin2++];
}
}
while (begin1 <= middle) pointer[k++] = array[begin1++];
while (begin2 <= right) pointer[k++] = array[begin2++];
copyarray(pointer, array, length, left);
if (pointer != NULL) free(pointer);
pointer = NULL;
} void 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 <malloc.h>
#include <inttypes.h>
#include <math.h>
#include <string.h>
#include <stdlib.h> /**
* 基数排序算法实现比较复杂,它是一种多关键字的排序算法,属于分类排序。因为基数
* 排序算法不需要过多比较,所以在数据较多的情况下,采用基数排序算法的效率要高于
* 其他的排序算法。
*/ #define SIZEMAX 200 //待排序元素的最大个数
#define N 10 //待排序元素的实际个数
#define NUMBERKEY_MAX 6 //关键字项数的最大值
#define RADIX 10 //关键字基数,10表示十进制数字可以分为十组 typedef struct listcell_struct {
int32_t key[NUMBERKEY_MAX]; //关键字
int32_t next;
} listcell_t; //静态链表的节点,存放待排序的元素 typedef struct list_struct {
listcell_t data[SIZEMAX]; //存储元素,data[0]为头节点
int32_t keynumber; //每个元素的当前关键字个数
int32_t length; //静态链表的当前长度
} list_t; //静态链表,存放元素序列 typedef int32_t addr[RADIX]; //指针数组的类型,用来指向每个链表的第一个节点和最后一个节点 void displaylist(list_t L); //输出链表中的元素
void display_staticlist(list_t L); //以静态链表的形式输出元素
void initlist(list_t *list, int32_t dest[], int32_t length);
int32_t transchar(char _char); //将字符转换为数字
void distribute(listcell_t data[], int32_t i, addr f, addr r); //分配
void collect(listcell_t data[], addr f, addr r); //收集
void radixsort(list_t *L); int32_t main(int32_t argc, char *argv[]) {
int32_t array[N] = {, , , , , , , , , };
list_t L;
initlist(&L, array, N);
printf("need sort number is %d, key number is %d\n", L.length, L.keynumber);
printf("before sort static list: ");
display_staticlist(L);
printf("before sort list: \n");
displaylist(L);
radixsort(&L);
printf("after sort: \n");
displaylist(L);
return ;
} //按数组序号形式输出静态链表
void displaylist(list_t L) {
int32_t i, j;
printf("no key addr \n");
for (i = ; i <= L.length; ++i) {
printf("%2d ", i);
for (j = L.keynumber - ; j >= ; --j) {
printf("%c", L.data[i].key[j]);
}
printf(" %d\n", L.data[i].next);
}
} //按链表形式输出静态链表
void display_staticlist(list_t L) {
int32_t i = L.data[].next, j;
while (i) {
for (j = L.keynumber - ; j >= ; --j)
printf("%c", L.data[i].key[j]);
printf(" ");
i = L.data[i].next;
}
printf("\n");
} //初始化静态链表L
void initlist(list_t *L, int32_t array[], int32_t length) {
char _char1[NUMBERKEY_MAX] , _char2[NUMBERKEY_MAX];
int32_t i, j;
int32_t max = array[];
for (i = ; i < length; ++i) { //将最大的元素存入max
if (max < array[i]) max = array[i];
}
(*L).keynumber = (int32_t)(log10(max)) + ; //求字关键字的个数
(*L).length = length; //待排序个数
for (i = ; i <= length; ++i) {
//itoa(array[i - 1], _char1 , 10); //将整型转换为字符,并存入_char
sprintf(_char1, "%d", array[i - ]);
//如果_char的长度<max的位数,则在_char前补'0'
for (j = strlen(_char1); j < (*L).keynumber; ++j) {
strcpy(_char2, "");
strcat(_char2, _char1);
strcpy(_char1, _char2);
}
//将每个元素的个位数存入key,作为关键字
for (j = ; j < (*L).keynumber; ++j) {
(*L).data[i].key[j] = _char1[(*L).keynumber - - j];
}
}
for (i = ; i < (*L).length; ++i)
(*L).data[i].next = i + ;
(*L).data[(*L).length].next = ;
} int32_t transchar(char _char) {
return _char - '';
} //为data数组中的第i个关键字key[i]建立radix个子表,使同一子表中元素的key[i]相同
//f[0...radix - 1]和r[0...radix - 1]分别指向各个子表中第一个和最后一个元素
void distribute(listcell_t data[], int32_t i, addr f, addr r) {
int32_t j, p;
for (j = ; j < RADIX; ++j) f[j] = ; //初始化各个子表
for (p = data[].next; p; p = data[p].next) {
j = transchar(data[p].key[i]); //将关键字转换为数字
if (!f[j]) { //f[j]是空表,则f[j]指示第一个元素
f[j] = p;
} else {
data[r[j]].next = p;
}
r[j] = p; //将p所指的节点插入第j个子表中
}
} //收集,按key[i]将f[0...radix - 1]所指各子表依次连接成一个静态链表
void collect(listcell_t data[], addr f, addr r) {
int32_t i;
int32_t temp;
for (i = ; !f[i]; ++i); //找第一个非空子表,为求后续函数
data[].next = f[i];
temp = r[i]; //r[0].next 指向第一个非空子表中的第一个节点
while (i < RADIX - ) {
for (i = i + ; i < RADIX - && !f[i]; ++i); //查找下一个非空子表
if (f[i]) {
data[temp].next = f[i];
temp = r[i];
}
}
data[temp].next = ; //temp指向最后一个非空子表中的最后一个节点
} //基数排序,使得L成为按关键字非递减的静态链表,L.r[0]为头节点
void radixsort(list_t *L) {
int32_t i;
addr f, r;
//由低位到高位一次对各关键字进行分配和收集
for (i = ; i < (*L).keynumber; ++i) {
distribute((*L).data, i, f, r); //第i次分配
collect((*L).data, f, r); //第i次收集
printf("the %d times collect result: ", i + );
display_staticlist(*L);
}
}

result.

MMORPG大型游戏设计与开发(服务器 游戏场景 事件)的更多相关文章

  1. MMORPG大型游戏设计与开发(游戏服务器 游戏场景 概述 updated)

    我们在玩游戏的时候,我们进入游戏后第一眼往往都是看到游戏世界中的场景,当然除了个别例外,因为那些游戏将游戏场景隐藏了起来,如文字游戏中的地点一样.既然我们接触了游戏世界的核心,那么作为核心的场景又包括 ...

  2. MMORPG大型游戏设计与开发(服务器 AI 概述)

    游戏世界中我们拥有许多对象,常见的就是角色自身以及怪物和NPC,我们可以见到怪物和NPC拥有许多的行为,比如说怪物常常见到敌对的玩家就会攻击一样,又如一些NPC来游戏世界中走来走去,又有些怪物和NPC ...

  3. MMORPG大型游戏设计与开发(服务器 游戏场景 动态场景与副本)

    场景的内容讲解到今天算是暂时划上一个句号了,接下来为大家讲解的是AI部分(大型AI),如果有兴趣的朋友不妨持续关注这些文章,大家一起学习和进步.动态场景和副本是场景中特殊的类型,副本在这里想必已经是无 ...

  4. MMORPG大型游戏设计与开发(服务器 游戏场景 核心详述)

    核心这个词来的是多么的高深,可能我们也因为这个字眼望而却步,也就很难去掌握这部分的知识.之所以将核心放在最前面讲解,也可以看出它真的很重要,希望朋友们不会错过这个一直以来让大家不熟悉的知识,同我一起进 ...

  5. MMORPG大型游戏设计与开发(概述)updated

    1.定义 MMORPG,是英文Massive(或Massively)Multiplayer Online Role-PlayingGame的缩写,即大型多人在线角色扮演游戏. 2.技术与知识 在这系列 ...

  6. MMORPG大型游戏设计与开发(客户端架构 part8 of vegine)

    脚本模块是游戏设计中争论比较多的话题,那是因为作为脚本本身所带来的利弊.其实这都无关紧要,取舍是人必须学会的一项技能,如果你不会取舍那么就让趋势给你一个满意的答复.自从魔兽世界以及传奇(世界)问世以来 ...

  7. MMORPG大型游戏设计与开发(server 游戏场景 事件)

    游戏截图 场景事件 一个完整的对象一般都拥有事件,至于什么是事件在这里就不多解释了. 在场景中的事件在天龙/武侠世界中的事件包含场景初始化.场景定时器.场景退出.玩家进入场景.角色升级.角色死亡.角色 ...

  8. MMORPG大型游戏设计与开发(服务器 游戏场景 地图和区域)

    地图的数据以及区域的信息是场景的重要组成部分,这些数据同时存在客户端和服务器,而且都是由编辑器生成的.那么保存的文件数据结构是怎样的?一张3D的场景地图又是怎样处理这些数据的?同时告诉大家这里同样只是 ...

  9. MMORPG大型游戏设计与开发(服务器 游戏场景 多线程)

    多线程在随着cpu发展应用的是越来越多,游戏场景因为其在服务器所占的数据量与逻辑复杂度的原因必须依赖于它.为什么场景要采用多线程?场景的线程是怎样的?场景的线程又是如何创建的?场景的线程又是怎样管理的 ...

随机推荐

  1. 详解Spring框架AOP(面向切面编程)

    最近在学习AOP,之前一直很不明白,什么是AOP?为什么要使用AOP,它有什么作用?学完之后有一点小小的感触和自己的理解,所以在这里呢就跟大家一起分享一下 AOP(Aspect-Oriented Pr ...

  2. C#+ArcEngine10.0+SP5实现鼠标移动动态显示要素属性信息

    为了解决鼠标移过动态显示要素属性的问题,我在网上先是查到的只能显示单个要素的属性,就是直接在arcmap中设置好的那个tips就可以显示,但是这种显示效果只是简单的实现了显示要素的属性值,可是没有对该 ...

  3. Java Enumeration接口

    Enumeration接口定义 Enumeration接口与Iterator接口用法比较 一. 1.Enumeration接口定义 public interface Enumeration<E& ...

  4. 关系型数据库与NOSQL

    本文转载自: http://www.cnblogs.com/chay1227/archive/2013/03/17/2964020.html(只作转载, 不代表本站和博主同意文中观点或证实文中信息) ...

  5. asp.net identity 介绍

    Asp.Net Identity 设计目标 微软在 asp.net 2.0 引入了 membership,为 asp.net 应用程序提供身份验证和授权功能.membership 假定用户在网站注册, ...

  6. [deviceone开发]-一个简单的表单示例

    一.简介 这个例子我们用do_ScrollView+do_LinearLayout来实现,当没有输入相关的值而去保存的时候,则把隐藏的几个提示Label显示出来,然后调用do_LinearLayout ...

  7. Linux0.11内核--内存管理之1.初始化

    [版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5597705.html ] Linux内核因为使用了内存分页机制,所以相对来说好理解些.因为内存 ...

  8. [转]File Descriptor泄漏导致Crash: Too many open files

    在实际的Android开发过程中,我们遇到了一些奇奇怪怪的Crash,通过sigaction再配合libcorkscrew以及一些第三方的Crash Reporter都捕获不到发生Crash的具体信息 ...

  9. IOS开发基础知识--碎片25

    1:使用@protocol实现delegate和datasource模式 #import <UIKit/UIKit.h> @protocol MyViewDataSource,MyView ...

  10. Android的四大组件之Activity

    Android的四大组件之Activity Activity:是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,B ...