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[] = {3, 13, 8, 9, 76, 45, 56, 99, 102, 15};
  int32_t length = sizeof(array) / sizeof(array[0]);
  bubblesort(array, length);  
  return 0;
}

void printarray(int32_t array[], int32_t length) {
  int32_t i;
  for (i = 0; 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 = 1;
  for (i = 1; i < length && 1 == flag; ++i) {
    flag = 0;
    for (j = 0; j < length - i; ++j) {
      if (array[j] > array[j + 1]) {
        temp = array[j];
        array[j] = array[j + 1];
        array[j + 1] = temp;
        flag = 1;
      }
    }
    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[] = {3, 15, 7, 3, 2, 11, 9, 33, 35, 18, 32};
  int32_t length = sizeof(array) / sizeof(array[0]);
  printf("before sort: ");
  displayarray(array, length);
  quicksort(array, length);
  printf("after sort: ");
  displayarray(array, length);
  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");
}

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 = 0; i < pivot; ++i)
    printf("%-4d", array[i]);
  printf("]");
  printf("%3d ", array[pivot]);
  printf("[");
  for (i = pivot + 1; 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 = 1;
  if (low < high) { //如果元素序列的長度大於1
    pivot = partition(array, low, high); //將待排序序列array[low...high]划分為兩部分
    _displayarray(array, length, pivot, count); //輸出每次划分的結果
    ++count;
    _quicksort(array, length, low, pivot - 1); //對左邊的子表進行遞歸排序,pivot是樞軸位置
    _quicksort(array, length, pivot + 1, high); //對右邊的子表進行遞歸排序
  }
}

void quicksort(int32_t array[], int32_t length) {
  _quicksort(array, length, 0, length - 1);
}

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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM