龍雲堯個人博客,轉載請註明出處。
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);
}
}
}