又快到雙十一,又是不少同仁們出血的日子,首先希望大家玩的開心。我曾經想要仔細的剖析場景的的每個組件,就像這里的聊天管道與尋路器,但是仔細閱讀別人代碼的時候才發現元件雖小但是實現並不簡單,因為有些東西還沒有完全想明白我就暫時不說其具體的實現過程,但是我會保證這些文章在后面會不斷更新,同時也希望對這方面有興趣和經驗的朋友們能夠指正。聊天這個我們都知道,因為它幾乎成了游戲或是生活中不可或缺的一部分,那么什么是尋路器?我想未必大家都知道什么是尋路器,不過我可以告訴大家的是你在游戲中自動尋路這個功能就是由該組件實現的。
一張截圖
聊天管道
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 = {{35, 33, 23, 67, 88, 99, 123, 232, 111}, 9}; 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 0; } int32_t seqsearch(table_t table, int32_t x) { int32_t i = 0; while (i < table.length && table.list[i] != x) ++i; if (table.list[i] == x) { return i + 1; } return 0; } int32_t displayarray(int32_t array[], int32_t length) { int32_t i; for (i = 0; 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 = {{12, 23, 35, 36, 56, 78, 86, 89, 91}, 9}; 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 0; } int32_t binarysearch(table_t table, int32_t x) { int32_t low, high, middle; low = 0, high = table.length - 1; //設置待查找元素的下界和上界 while (low <= high) { middle = (low + high) / 2; if (table.list[middle] == x) //如果找到元素,則返回該元素所在位置 return middle + 1; else if (table.list[middle] < x) //如果middle所在元素小於查找元素則向右移動low的位置 low = middle + 1; else if (table.list[middle] > x) //如果middle所在元素大於查找元素則向左移動high的位置 high = middle - 1; } return 0; } void displayarray(int32_t array[], int32_t length) { int32_t i; for (i = 0; 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 = {{8, 13, 25, 19, 22, 29, 46, 38, 30, 35, 50, 60, 49, 57, 55, 65, 70, 89, 92, 70}, 20}; indextable_t indextable = {{25, 0}, {46, 5}, {60, 10}, {92, 15}}; int32_t x, position, i; printf("index table max value: \n"); for (i = 0; i < 4; ++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, 4, 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 0; } 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 = 0; i < m; ++i) { //通過索引表確定要查找元素在主表中的單元 if (indextable[i].maxvalue >= x) break; } if (i >= m) return 0; //如果查找元素不再表table中,返回 j = indextable[i].index; //從第i個單元序號j開始查找元素x if (i < m - 1) { //b1為第j單元的長度 b1 = indextable[i + 1].index - indextable[i].index; } else { b1 = table.length - indextable[i].index; } while (j < indextable[i].index + b1) { if (table.list[j] == x) { //找到 return j + 1; } ++j; } return 0; } void displayarray(int32_t array[], int32_t length) { int32_t i; for (i = 0; i < length; ++i) printf("%4d", array[i]); printf("\n"); }