虛擬駕駛環境搭建(四)

龍雲堯個人博客,轉載請註明出處。

CSDN地址:http://blog.csdn.net/michael753951/article/details/75074051

個人blog地址:http://yaoyl.cn/huan-jing-da-jian-si-2/


障礙物移動的改進

在之前的版本中.我們的障礙物移動和場景移動放在同一個for循環中,雖然減少了代碼的操作,但是很容易出現邊界問題,程序運行中往往會出現障礙物驟現,或者障礙物還未抵達車前方便突然消失的情況,爲了修改這出bug,我將重寫這部分代碼.

需求分析

無腦寫代碼的多數結果都是bug不斷,並且寫完後文就忘記前文.爲了提高代碼的清晰度和準確性,挺屍幫我們捋清思路,我們先通過寫僞代碼的方式整理一下我們的程序有哪些需求,以及粗略的實現方式.

需求

障礙物能夠從左側樓棟出現,到達路中央之後,將停留一小段時間(等待車撞上).

對這個過程進行分解分析,我們可以大致得到如下流程:

  • 障礙物出現的時機: 左側有障礙物 & 距離上次消失已經有10s以上
  • 障礙靜止時機: 已經達到路中間, 並且停留時間沒有達到2s
  • 障礙物消失詩句時機: 停留2s之後,障礙物消失

僞代碼

  • 首先判斷障礙物是否已經消失,然後判斷左側是否有障礙物,然後檢查消失時間是否已經達到10s,如果滿足條件,就更新appear標誌, 讓障礙物開始移動
  • 開始步進障礙物, 直到達到邊界, 此時更新appear_tmp, 更新appear標誌, 記錄下當前時間
  • 如果當前狀態爲靜止, 並且停留時間還未到達2s,保持pos不變
  • 否則如果停留時間超過2s,就將appear更新爲消失, 讓障礙物消失, 同時用appear_tmp記錄下消失的時間, 方便之後判斷障礙物的出現時機

代碼實現

    // 先獲取左側建築情況
    int left_temp = building_left_flag;
    // bdw_appear有3個值, 0表示已經消失, 1表示正在進行移動, 2表示移動到邊界,已經靜止
    if(bdw_appear == 0) {
        if(left_temp >> 11 & 0b1 == 1) {
            time(&appear);
            // 如果距離上次出現已經5s,就更新記錄,同時更新flag
            if(appear - appear_tmp >= 5){
                appear_tmp = appear;
                bdw_appear = 1;
            }
        }
    }else if(bdw_appear == 1){
        glBindTexture(GL_TEXTURE_2D, texture[4]);
        glLoadIdentity();
        glTranslatef(child_run_len, -1.0f, -7.0f);
        glCallList(children);
        if(child_run_len >= -0.5) {
            //child_run_len = -3.0f;
            //bdw_appear = false;
            // 剛移動到邊界
            if(bdw_appear == 1){
                time(&appear_tmp);
                child_pos = -7.0f;
                bdw_appear = 2;
            }
            child_run_len = -0.5f;
        }else{
            // 小孩的速度恆定
            child_run_len += 0.1f;
        }
    }else{
        time(&appear);
        // 如果距離上次出現已經5s,就更新記錄,同時更新flag
        if(appear - appear_tmp >= 2){
            appear_tmp = appear;
            child_run_len = -3.0f;
            bdw_appear = 0;
        }else{
            glBindTexture(GL_TEXTURE_2D, texture[4]);
            glLoadIdentity();
            // 障礙物的pos還要加上run_len, 這樣能夠讓障礙物在達到路中央靜止之後, 和周圍物體一起移動,產生向人靠近的感覺
            glTranslatef(child_run_len, -1.0f, child_pos+run_len);
            glCallList(children);
        }
    }

實現障礙物從兩側隨機出現

爲了和真實駕駛更加相似,我們不應該讓障礙物只從單側出現,而是因該讓其兩側都有可能出現.因此,我們需要在原來的代碼上進行進一步的修改.

需求分析

需求

首先我們暫時讓不倒翁的出現有兩種情況, 情況一, 從左側出現, 情況二, 從兩側隨機出現. 通過按鍵’c’來控制模式的轉換(改變appear_mode的值).

因此, 當我們按下’c’鍵時, 需要對模式進行轉換. 接下來在DrawGLScene中將根據appear_mode的值進行一系列操作. 如果appear_mode爲默認的0, 就讓障礙物從左側出現, 如果appear_mode爲1, 就讓障礙物從兩側出現.

如果障礙物從兩側出現的話, 每次障礙物將要出現的時候, 我們需要用一個flag標誌保存障礙物本次出現是從左側出現還是右側出現. 在繪製障礙物的時候, 我們將通過這個flag來判斷物體是如何運動.

  • 障礙物出現的時機: 本身已經消失, 距離上次消失已經有10s以上, 決定好從哪一側出現, 並且該側有樓棟
  • 障礙物移動的時機: 本身已經出現, 根據上一步已經得到的flag判定是向左還是向右, 直到到臨界點
  • 障礙物靜止的時機: 已經達到路中間,並且停留時間並未超過2s
  • 障礙物消失的時機: 已經靜止超過2s

僞代碼

  • 首先我們需要在KeyPressed函數中, 添加按鍵’c’的控制事件, 另其對appear_mode進行修改.
  • 接下來在DrawGLScene中, 我們將對這個appear_mode進行判斷. 如果appear_mode爲0,就按照之前的代碼執行. 如果appear_mode爲1, 則進入兩側出現事件.
  • 當appear_mode爲1時, 如果當前狀態爲消失, 如果當前已經消失10s以上, 則隨機決定在哪應該出現障礙物, 然後檢查該側是否有樓棟, 如果有樓棟, 則保存裁決位置(左或者右), 同時更新當前狀態爲移動
  • 當appear_mode爲1時, 當前狀態爲移動時, 根據裁決, 如果裁決決定從左側出來, 則起點設置爲左側, 同時,不斷增加child_run_len,直到到達邊界; 如果裁決決定從右側出來, 則起點設置爲1.0f位置, 同時不斷減小, 直到到達-0.5f位置停止.
  • 停止時, 將appear_mode設置爲2, 記錄開始時間, 在原地停留兩秒之後, 消失.

代碼實現

    int left_temp = building_left_flag;
    int right_temp = building_right_flag;
    if(appear_mode == 0) {
        // bdw_appear有3個值, 0表示已經消失, 1表示正在進行移動, 2表示移動到邊界,已經靜止
        if(bdw_appear == 0) {
            if(left_temp >> 11 & 0b1 == 1) {
                time(&appear);
                // 如果距離上次出現已經5s,就更新記錄,同時更新flag
                if(appear - appear_tmp >= 5) {
                    appear_tmp = appear;
                    bdw_appear = 1;
                    child_run_len = -3.0f;
                }
            }
        } else if(bdw_appear == 1) {
            glBindTexture(GL_TEXTURE_2D, texture[4]);
            glLoadIdentity();
            glTranslatef(child_run_len, -1.0f, -7.0f);
            glCallList(children);
            if(child_run_len >= -0.5) {
                //child_run_len = -3.0f;
                //bdw_appear = false;
                // 剛移動到邊界
                if(bdw_appear == 1) {
                    time(&appear_tmp);
                    child_pos = -7.0f;
                    bdw_appear = 2;
                }
                child_run_len = -0.5f;
            } else {
                // 小孩的速度恆定
                child_run_len += 0.1f;
            }
        } else {
            time(&appear);
            // 如果距離上次出現已經5s,就更新記錄,同時更新flag
            if(appear - appear_tmp >= 2) {
                appear_tmp = appear;
                child_run_len = -3.0f;
                bdw_appear = 0;
            } else {
                glBindTexture(GL_TEXTURE_2D, texture[4]);
                glLoadIdentity();
                glTranslatef(child_run_len, -1.0f, child_pos+run_len);
                glCallList(children);
            }
        }
    }else if(appear_mode == 1) {
        if(bdw_appear == 0) {
            time(&appear);
            if(appear - appear_tmp >= 5){
                // 奇數爲左側, 偶數爲右側
                if(rand() & 0b1 == 1) {
                    if(left_temp >> 11 & 0b1 == 1) {
                        time(&appear);
                        appear_tmp = appear;
                        bdw_appear = 1;
                        left_or_right_flag = 1;
                        child_run_len = -3.0f;
                    }
                }else{
                    if(right_temp >> 11 & 0b1 == 1) {
                        time(&appear);
                        appear_tmp = appear;
                        bdw_appear = 1;
                        left_or_right_flag = 0;
                        child_run_len = 1.0f;
                    }
                }
            }
        } else if(bdw_appear == 1) {
            if(left_or_right_flag == 1){
                glBindTexture(GL_TEXTURE_2D, texture[4]);
                glLoadIdentity();
                glTranslatef(child_run_len, -1.0f, -7.0f);
                glCallList(children);
                if(child_run_len >= -0.5) {
                    //child_run_len = -3.0f;
                    //bdw_appear = false;
                    // 剛移動到邊界
                    if(bdw_appear == 1) {
                        time(&appear_tmp);
                        child_pos = -7.0f;
                        bdw_appear = 2;
                    }
                    child_run_len = -0.5f;
                } else {
                    // 小孩的速度恆定
                    child_run_len += 0.1f;
                }
            }else{
                glBindTexture(GL_TEXTURE_2D, texture[4]);
                glLoadIdentity();
                glTranslatef(child_run_len, -1.0f, -7.0f);
                glCallList(children);
                if(child_run_len <= -0.5f) {
                    if(bdw_appear == 1) {
                        time(&appear_tmp);
                        child_pos = -7.0f;
                        bdw_appear = 2;
                    }
                } else {
                    child_run_len -= 0.1f;
                }
            }
        } else {
            time(&appear);
            // 如果距離上次出現已經5s,就更新記錄,同時更新flag
            if(appear - appear_tmp >= 2) {
                appear_tmp = appear;
                child_run_len = -3.0f;
                bdw_appear = 0;
            } else {
                glBindTexture(GL_TEXTURE_2D, texture[4]);
                glLoadIdentity();
                glTranslatef(child_run_len, -1.0f, child_pos+run_len);
                glCallList(children);
            }
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章