7_DoubleBuffer 遊戲編程中的雙緩衝模式

來源:互聯網
上載者:User

標籤:

### double buffer 雙緩衝簡單說: 當一個緩衝被讀取的時候,往另一個緩衝裡寫入, 如此交替#### the pattern有兩個緩衝執行個體,一個是 current buffer, 一個是next buffer從current buffer讀取資訊, 往next buffer裡寫入資訊.swap操作,進行兩種buff的身份切換#### 何時使用1 需要增量修改的狀態2 在修改的過程中需要進行訪問3 當訪問資料的時候,不會探索資料正在被寫入4 讀操作不用等待寫的操作完成#### 注意事項1 swap操作比較耗時2 必須有兩個buffer, 記憶體消耗變大#### Sample Code####一個幀緩衝的例子```class Framebuffer{public:  Framebuffer() { clear(); }  void clear()  {    for (int i = 0; i < WIDTH * HEIGHT; i++)    {      pixels_[i] = WHITE;    }  }  void draw(int x, int y)  {    pixels_[(WIDTH * y) + x] = BLACK;  }  const char* getPixels()  {    return pixels_;  }private:  static const int WIDTH = 160;  static const int HEIGHT = 120;  char pixels_[WIDTH * HEIGHT];};// 問題版本class Scene{public:  // 每一幀執行      void draw()  {    buffer_.clear();    buffer_.draw(1, 1);    buffer_.draw(4, 1);    // 問題! video driver 可以在任何時候讀取pixels, 可能會讀到非法值    buffer_.draw(1, 3);    buffer_.draw(2, 4);    buffer_.draw(3, 4);    buffer_.draw(4, 3);  }         Framebuffer& getBuffer() { return buffer_; }private:  Framebuffer buffer_;     void swap()  {    // Just switch the pointers.    Framebuffer* temp = current_;              current_ = next_;    next_ = temp;  }  };// 使用double bufferclass Scene{public:  Scene()  : current_(&buffers_[0]),    next_(&buffers_[1])  {}  // video driver 只會從 current裡擷取pixel  void draw()  {    next_->clear();    next_->draw(1, 1);    // ...    next_->draw(4, 3);    swap();  }  Framebuffer& getBuffer() { return *current_; }private:  void swap()  {    // Just switch the pointers.    Framebuffer* temp = current_;    current_ = next_;    next_ = temp;  }  Framebuffer  buffers_[2];  Framebuffer* current_;  Framebuffer* next_;};```##### Artificial unintelligence```class Actor{public:  Actor() : slapped_(false) {}  virtual ~Actor() {}  virtual void update() = 0;  void reset()      { slapped_ = false; }  void slap()       { slapped_ = true; }  bool wasSlapped() { return slapped_; }private:  bool slapped_;};// 每一幀都會調用actor的update, ,所有的actor需要同時進行更新// actor之間可以互動, 例如擊打class Stage{public:  void add(Actor* actor, int index)  {    actors_[index] = actor;  }  void update()  {    for (int i = 0; i < NUM_ACTORS; i++)    {      actors_[i]->update();      actors_[i]->reset();    }  }private:  static const int NUM_ACTORS = 3;  Actor* actors_[NUM_ACTORS];};// 同一時間, 只會有一個actor執行updateclass Comedian : public Actor{public:  void face(Actor* actor) { facing_ = actor; }  virtual void update()  {    if (wasSlapped()) facing_->slap();  }private:  Actor* facing_;};// 面對某人 harry ------> balay ------> chump ^                              | | -------------------------------v   Stage stage;Comedian* harry = new Comedian();Comedian* baldy = new Comedian();Comedian* chump = new Comedian();harry->face(baldy);baldy->face(chump);chump->face(harry);stage.add(harry, 0);stage.add(baldy, 1);stage.add(chump, 2);harry->slap();stage.update();// slap harry ---slap---> balay --slap----> chump ^                                   | | ----------------slap---------------v 正確的結果  #如果把三人的執行順序換一下, 結果將不正確#stage.add(harry, 2);stage.add(baldy, 1);stage.add(chump, 0);只有harry slap 了baldybuffered slaps// 把slap用buffer記錄下來class Actor{public:  Actor() : currentSlapped_(false) {}  virtual ~Actor() {}  virtual void update() = 0;  void swap()  {    // Swap the buffer.    currentSlapped_ = nextSlapped_;    // Clear the new "next" buffer.    nextSlapped_ = false;  }  void slap()       { nextSlapped_ = true; }  bool wasSlapped() { return currentSlapped_; }private:  bool currentSlapped_;  bool nextSlapped_;};void Stage::update(){  for (int i = 0; i < NUM_ACTORS; i++)  {    actors_[i]->update();  }  for (int i = 0; i < NUM_ACTORS; i++)  {    actors_[i]->swap();  }}```#### buffer swapswap需要鎖住兩個buffer, 所需需要盡量的輕量快速1 交換指標 引用    1.快速    2.外部代碼不能儲存buffer指標    3 當前的資料,是兩幀之前的資料(讀current的同時,資料寫入了next)    2 buffer之間拷貝資料    如果無法進行swap,可以把next的資料copy到current    如果數量小則沒什麼問題,如果大則會耗時    ```當很多個物件都有需要swap操作時, 會很慢下面這個例子,不用swap,而是slap的時候修改了next的值class Actor{public:  static void init() { current_ = 0; }  static void swap() { current_ = next(); }  void slap()        { slapped_[next()] = true; }  bool wasSlapped()  { return slapped_[current_]; }private:  static int current_;  static int next()  { return 1 - current_; }  bool slapped_[2];};```#### See alsodouble buffer 模式在圖形編程上應用廣泛You can find the Double Buffer pattern in use in almost every graphics API out there. For example, OpenGL has swapBuffers(), Direct3D has “swap chains”, and Microsoft’s XNA framework swaps the framebuffers within its endDraw() method.

 

7_DoubleBuffer 遊戲編程中的雙緩衝模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.