2014-09-24 42 views
0

我正試圖找出一種在OpenGL中執行以下行爲的有效方法。OpenGL中的蠕蟲爬行運動?

我給一個類似蠕蟲的傢伙製作了一個動畫(基本上我想要一個帶有可見眼睛的矩形 - 沒有什麼複雜的),它應該通過擴展到其前部長度的兩倍來移動,並且從背部。當它到達窗口邊緣時,蠕蟲會反轉方向。

我在獲得正確的動作方面存在很大的困難,並且在定位眼睛時有些微小的困難。如果我只是畫兩個多邊形一個其他同它們的相對位置後,我可以期待後者被畫了前者?我現在的動議呈現出一個無限循環,我無法在概念上改變另一種方法。我無法弄清楚循環結構是否有雙倍/收縮運動並有效地終止方法。

電流以下代碼:

#define GLUT_DISABLE_ATEXIT_HACK 
#include <GL/glut.h> 
#include <GL/gl.h> 

float wormX = 0; 
float wormY = 0; 
float wormWidth = 100; 
float wormHeight = 75; 
bool wormCrawl = true; 

void timer(int value) 
{ 
const int w = glutGet(GLUT_WINDOW_WIDTH); 
if(wormX + wormWidth >= w/2) //If worm hits edge, reverse direction! 
{ 
    wormX = 2; 
} 

while(wormCrawl) 
{ 
    wormX += 2; //Move the worm 
    wormWidth = 2*wormWidth; //Extend the front 
    wormWidth = (1/2)*wormWidth; //Retract the back 

} 

glutTimerFunc(16, timer, 0); 
glutPostRedisplay(); 
} 

void display() 
{ 
glClearColor(0.0, 0.0, 0.0, 0.0); 
glClear(GL_COLOR_BUFFER_BIT); 

const int w = glutGet(GLUT_WINDOW_WIDTH); 
const int h = glutGet(GLUT_WINDOW_HEIGHT); 

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(-w/2, w/2, -h/2, h/2, -1.0, 1.0); 

glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 

const float leftCorner = wormX; 
const float rightCorner = leftCorner + wormWidth; 
const float bottomCorner = wormY; 
const float topCorner = bottomCorner + wormHeight; 
//Worm 
glBegin(GL_POLYGON); 
    glColor3f(0.0, 1.0, 0.0); 
    glVertex2d(leftCorner, topCorner); 
    glVertex2d(rightCorner, topCorner); 
    glVertex2d(rightCorner, bottomCorner); 
    glVertex2d(leftCorner, bottomCorner); 
glEnd(); 
//Worm eye 
glBegin(GL_POLYGON); 
    glColor3f(0.0, 0.0, 0.0); 
    glVertex2d(leftCorner, topCorner); 
    glVertex2d(leftCorner + 10, topCorner); 
    glVertex2d(leftCorner + 10, bottomCorner); 
    glVertex2d(leftCorner, bottomCorner); 
glEnd(); 

glutSwapBuffers(); 
} 

int main(int argc, char** argv) 
{ 
glutInit(&argc, argv); 
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); 
glutInitWindowSize(500, 500); 
glutInitWindowPosition(0, 0); 
glutCreateWindow ("Inchworm Crawl"); 

glutDisplayFunc(display); 
glutTimerFunc(0, timer, 0); 
glutMainLoop(); 

return 0; 
} 
+0

@ user2864740只有在使用深度緩衝區時,只有問題中的代碼沒有執行深度緩衝。 – duskwuff 2014-09-24 22:09:25

+0

@duskwuff然後這就是它自己的問題:< – user2864740 2014-09-24 22:10:19

+0

你認爲在這種情況下使用深度緩衝是可取的,還是有其他選擇?我不是最熟悉使用深度緩衝區實現,但我會看看文檔。 – 2014-09-24 22:12:55

回答

1

所以第一關,我們想使生活變得更輕鬆,你應該嘗試抽象的蠕蟲一類。我假設你可能想繼續進行此後的發展,但無論如何它仍然是一個好習慣。這也將使我們的平局調用更容易。

好的,假設我們現在有我們的Worm類,該類將具有它自己的繪圖函數,我們想要儘可能簡單地在我們的主函數中保留我們的函數display()中的繪圖函數。想象一下,如果你想繪製另一種蠕蟲,你將不得不做些什麼。

所以在你的蠕蟲類的draw()方法是這個樣子:

void Worm::draw() 
{ 
    const float leftCorner = wormX; 
    const float rightCorner = leftCorner + wormWidth; 
    const float bottomCorner = wormY; 
    const float topCorner = bottomCorner + wormHeight; 
    //Worm 
    glBegin(GL_POLYGON); 
     glColor3f(0.0, 1.0, 0.0); 
     glVertex2d(leftCorner, topCorner); 
     glVertex2d(rightCorner, topCorner); 
     glVertex2d(rightCorner, bottomCorner); 
     glVertex2d(leftCorner, bottomCorner); 
    glEnd(); 
    //Worm eye 
    glBegin(GL_POLYGON); 
     glColor3f(0.0, 0.0, 0.0); 
     glVertex2d(leftCorner, topCorner); 
     glVertex2d(leftCorner + 10, topCorner); 
     glVertex2d(leftCorner + 10, bottomCorner); 
     glVertex2d(leftCorner, bottomCorner); 
    glEnd(); 
} 

好了,這只是它的基礎知識,但我還沒有回答您的實際問題。我不確定你使用的是哪個版本的freeglut,但希望你有最新的。一般來說,如果你打算做的不僅僅是渲染,你應該儘量遠離glutmainloop();。它基本上阻止你在渲染循環之外執行任何邏輯,這實際上意味着程序中的所有內容都將被鎖定到幀速率。相反,您應該着眼於在主函數中編寫遊戲循環,然後在每次渲染幀時調用glutmainloopevent()

所以現在更多的動作,一旦你創建了你的遊戲循環,邏輯上你可以把所有的更新功能放在這裏,在循環結束時,你可以調用glutmainloopevent()注意這個循環也是半無限循環。它會在一些標誌爲真的時候運行,然後一旦蠕蟲蠕動到足夠的時候就可以終止它。 :P

所以現在我們的蠕蟲類,我們可以把我們的蠕蟲和增加他的寬度,我們可以把它像move()添加更多的功能。而且爲了簡化事情,我們可以爲我們的蠕蟲添加一個標誌,告訴我們他是否應該縮小或增長。這只是一個布爾值,在創建我們的蠕蟲對象時被初始化爲false。

void Worm::move(bool direction) 
{ 
    if(growing) 
    { 
     wormWidth += 1; 
     if(wormWidth > thresholdWidth) 
     { 
      growing = false; 
     } 
    } 
    else 
    { 
     wormWidth += 1; 
     if(wormWidth > thresholdWidth) 
     { 
      growing = false; 
     } 
    } 
    if(direction) 
    { 
     wormx += 1; 
    } 
    else 
    { 
     wormx -= 1; 
    } 
} 

現在我還沒有測試過這個可能,但我會想象它應該做些什麼接近你正在尋找的東西。我目前沒有在我的工作電腦上安裝glut,也沒有openGL。但是,如果這並不完全符合你的要求,請給我一些評論,當我下班回家時我可以看一看。最後要注意的是,你也可以在你的遊戲循環中調用你的移動函數,現在對於你的遊戲循環,你可能只需要一個while循環來做這件事,但最終你可以設置它只更新X每秒的次數,並繪製每秒的Y次。

有一點需要注意的是,因爲你不是每幀畫出一件以上的東西,它不會有所作爲。您可以繼續繪製蠕蟲,這就是gLClear()函數爲您所做的事情,它正在清除當前在顏色緩衝區中的所有內容,如果您忙於顯式使用3D的應用程序,則還需要添加深度緩衝區,否則不會按照正確的順序繪製,您可能會得到z戰鬥或某些東西被實際背後的東西吸引。

希望我沒有得到切線,這篇文章可以對你有一定的價值!

Goodluck!

+0

如果你需要一個遊戲循環/主循環的例子,我可以編輯我的文章並添加它。 – Daniel 2014-09-25 04:58:32

+0

感謝您的深入解答!這不是我想要的,但它給了我一些想法。不過,我仍然堅持一點。 我想讓蠕蟲像尺w一樣移動。所以在前進時它的寬度應該加倍,然後在重複運動之前縮回原始大小。自那時起,我已經明白了眼睛的畫面,所以這是真的! :) – 2014-09-25 15:51:21

+0

我建議可能有一些蠕蟲會延長的幀數,如15幀,如果你以每秒60幀的速度繪製,這意味着蠕蟲會擴展1/4秒。因此,在您的角色繪製功能中,您可以跟蹤您繪製了多少幀,使用60幀後的模運算符返回到0。然後,您可以每15幀反轉增長/縮小標誌。知道它正在擴展15幀,你可以計算它們在這些幀結束時的長度。這不是一個很乾淨的解決方案,但它應該完成工作。 – Daniel 2014-09-25 17:45:00