[OpenGL]音樂節奏遊戲(1)-UI設計

Posted by John on 2017-02-24
Words 1.6k and Reading Time 8 Minutes
Viewed Times

大三上學期計算機圖學的期末專題,我們這組做的是音樂節奏遊戲,起因突然想到曾經網路上好像有完過類似的所以就想來做這個,不然原本是打算用之前Unity專題或隨便做個動畫交上去交差了事的。


  • 遊戲名稱:MusicDance
  • 開發語言:C/C++ with API(OpenGL)
  • 開發時程:2天(熬了一整夜…)
  • 遊戲說明:音樂節奏遊戲,當上下左右的符號掉到對應的框框中,按下對應的按鍵可根據按下的時機獲得不同的分數。
    • 遊戲具有Combo系統,Combo數到達一定值以上會有額外分數加乘。
  • Demo影片:Youtube
  • 遊戲畫面:

接下來大致介紹一下是如何設計的:

首先是UI,先用gluOrtho2D這個函數設置好Clipping Window,接下來就是開始設計UI介面的每個點座標、箭頭的大小、輔助線的位置座標。設計完就開始畫圖瞜!長方形的部份就用glRecti(),文字則用glutBitmapCharacter()來繪製。

10

遊戲介面程式碼如下:

這是上半部介面的Code,這邊要注意的是Score和COMBO都是會隨著時間變動的,並且沒有COMBO的時候是不應該顯示COMBO數的

void top_UI()
{
int shift = 0;
char text_musicname[] = "MUSIC NAME: What Makes You Beautiful";
char text_score[] = "SCORE:";
char text_stop[] = "EXIT";
char s[30] = { 0 };
char c[30] = {0};
//頂部的視窗
//線條寬度:5
glColor3f(1.0f, 1.0f, 1.0f);
glRecti(0, 580, 500, 650);
glColor3f(0.0f, 0.0f, 0.0f);
glRecti(5, 585, 495, 645);
//頂部功能選單
//線條寬度:3
glColor3f(1.0f, 1.0f, 1.0f);//底色:白色
glRecti(422, 550, 500, 580);
glColor3f(0.0f, 0.0f, 0.0f);//兩個功能選框
glRecti(425, 553, 497, 580);
//------------------------------------------------------------------------------------------------
//| 頂部功能選單文字 |
//------------------------------------------------------------------------------------------------
glColor3f(1.0f, 1.0f, 1.0f);//白色
//MUSIC NAME
shift = 0;
for (int i = 0; i < strlen(text_musicname); ++i)
{
glRasterPos2i(100 + shift, 610);
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, text_musicname[i]);
shift += glutBitmapWidth(GLUT_BITMAP_9_BY_15, text_musicname[i]);
}
//SCORE
shift = 0;
for (int i = 0; i < strlen(text_score); ++i)
{
glRasterPos2i(100 + shift, 590);
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, text_score[i]);
shift += glutBitmapWidth(GLUT_BITMAP_9_BY_15, text_score[i]);
}
//SCORE VARABLE
itoa(score, s, 10);
shift = 0;
glColor3f(1.0f, 0.90f, 0.0f);//黃色
for (int i = 0; i < strlen(s); ++i)
{
glRasterPos2i(160 + shift, 590);//結束座標(160,590)
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, s[i]);
shift += glutBitmapWidth(GLUT_BITMAP_9_BY_15, s[i]);
}

//COMBO VARABLE
itoa(combo, c, 10);
shift = 0;
if (combo != 0)
{

if (combo <= 5)
{
glColor3f(1.0f, 0.90f, 0.0f);//黃色
}
else if (combo <= 10)
{
glColor3f(1.0f, 0.60f, 0.0f);//橘色
}
else if (combo <= 15)
{
glColor3f(1.0f, 0.0f, 0.0f);//紅
}
else if (combo <= 20)
{
glColor3f(1.0f, 0.0f, 1.0f);//紫
}
for (int i = 0; i < strlen(c); ++i)
{
glRasterPos2i(40 + shift, 530);//結束座標(160,590)
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, c[i]);
shift += glutBitmapWidth(GLUT_BITMAP_TIMES_ROMAN_24, c[i]);
}
}
glColor3f(1.0f, 1.0f, 1.0f);//白色
//EXIT
shift = 0;
for (int i = 0; i < strlen(text_stop); ++i)
{
glRasterPos2i(445 + shift, 563);
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, text_stop[i]);
shift += glutBitmapWidth(GLUT_BITMAP_9_BY_15, text_stop[i]);
}
}

這是下半部介面的Code

void buttom_UI()
{
//底部的視窗
//線條寬度:5
glColor3f(1.0f, 0.0f, 0.0f);
glRecti(0, 0, 500, 70);
glColor3f(0.0f, 0.0f, 0.0f);
glRecti(5, 5, 495, 65);
glColor3f(1.0f, 0.0f, 0.0f);

//輔助線
int shift = 0;
for (int i = 1; i <= 4; ++i)
{
glBegin(GL_LINES);
glColor3f(1.0, 0.0, 0.0);
glVertex2i(100 + shift, 70);
glVertex2i(100 + shift, 550);
glEnd();

//UI:上下左右
glPushMatrix();
glTranslatef(75 + shift, 20, 0.0);
arrow_Exterior_color.r = 0.0;
arrow_Exterior_color.g = 1.0;
arrow_Exterior_color.b = 0.0;
glColor3f(arrow_Exterior_color.r, arrow_Exterior_color.g, arrow_Exterior_color.b);
glCallList(UI_Up + (i – 1));
glPopMatrix();
shift += 100;
}
//EXIT
shift = 0;
for (int i = 0; i < strlen(text_stop); ++i)
{
glRasterPos2i(445 + shift, 563);
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, text_stop[i]);
shift += glutBitmapWidth(GLUT_BITMAP_9_BY_15, text_stop[i]);
}
}

這裡的箭頭是用glCallList()來做的,所以需要先做好上下左右的箭頭
Arrow_LIST()這個function裡面除了UI的空心箭頭,還有之後遊戲的實心箭頭,之後會用到

void Arrow_LIST()//List Obj
{
//————————————————————————————————
//| UI介面的上下左右: |
//————————————————————————————————
glNewList(UI_Up, GL_COMPILE);//上
//外層
glBegin(GL_POLYGON);
glVertex2f(15, 0);
glVertex2f(35, 0);
glVertex2f(35, 20);
glVertex2f(15, 20);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(50, 20);
glVertex2f(25, 40);
glVertex2f(0, 20);
glEnd();

//內層
glPushMatrix();
glTranslatef(25 – (25 * 0.9), 20 – (20 * 0.9), 0.0);
glColor3f(arrow_interior_color.r, arrow_interior_color.g, arrow_interior_color.b);
glBegin(GL_POLYGON);
glVertex2f(15 * 0.9, 0 * 0.9);
glVertex2f(35 * 0.9, 0 * 0.9);
glVertex2f(35 * 0.9, 20 * 0.9 + 0.5);
glVertex2f(15 * 0.9, 20 * 0.9 + 0.5);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(50 * 0.9, 20 * 0.9 + 0.5);
glVertex2f(25 * 0.9, 40 * 0.9);
glVertex2f(0 * 0.9, 20 * 0.9 + 0.5);
glEnd();
glPopMatrix();

glEndList();

glNewList(UI_Down, GL_COMPILE);//下
//外層
glBegin(GL_POLYGON);
glVertex2f(15, 40);
glVertex2f(35, 40);
glVertex2f(35, 20);
glVertex2f(15, 20);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(50, 20);
glVertex2f(25, 0);
glVertex2f(0, 20);
glEnd();
//內層
glPushMatrix();
glTranslatef(25 – (25 * 0.9), 20 – (20 * 0.9), 0.0);
glColor3f(arrow_interior_color.r, arrow_interior_color.g, arrow_interior_color.b);
glBegin(GL_POLYGON);
glVertex2f(15 * 0.9, 40 * 0.9);
glVertex2f(35 * 0.9, 40 * 0.9);
glVertex2f(35 * 0.9, 20 * 0.91);
glVertex2f(15 * 0.9, 20 * 0.91);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(50 * 0.9, 20 * 0.91);
glVertex2f(25 * 0.9, 0 * 0.9);
glVertex2f(0 * 0.9, 20 * 0.91);
glEnd();
glPopMatrix();
glEndList();

glNewList(UI_Right, GL_COMPILE);//右
glBegin(GL_POLYGON);
glVertex2f(0, 10);
glVertex2f(0, 30);
glVertex2f(20, 30);
glVertex2f(20, 10);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(20, 40);
glVertex2f(20, 0);
glVertex2f(40, 20);
glEnd();
//內層
glPushMatrix();
glTranslatef(20 – (20 * 0.9), 20 – (20 * 0.9), 0.0);
glColor3f(arrow_interior_color.r, arrow_interior_color.g, arrow_interior_color.b);
glBegin(GL_POLYGON);
glVertex2f(0 * 0.9, 10 * 0.9);
glVertex2f(0 * 0.9, 30 * 0.9);
glVertex2f(20 * 0.9 + 1, 30 * 0.9);
glVertex2f(20 * 0.9 + 1, 10 * 0.9);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(20 * 0.9 + 1, 40 * 0.9);
glVertex2f(20 * 0.9 + 1, 0 * 0.9);
glVertex2f(40 * 0.9, 20 * 0.9);
glEnd();
glPopMatrix();
glEndList();

glNewList(UI_Left, GL_COMPILE);//左
glBegin(GL_POLYGON);
glVertex2f(40, 10);
glVertex2f(40, 30);
glVertex2f(20, 30);
glVertex2f(20, 10);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(20, 40);
glVertex2f(20, 0);
glVertex2f(0, 20);
glEnd();

//內層
glPushMatrix();
glTranslatef(20 – (20 * 0.9), 20 – (20 * 0.9), 0.0);
glColor3f(arrow_interior_color.r, arrow_interior_color.g, arrow_interior_color.b);
glBegin(GL_POLYGON);
glVertex2f(40 * 0.9, 10 * 0.9);
glVertex2f(40 * 0.9, 30 * 0.9);
glVertex2f(20 * 0.91, 30 * 0.9);
glVertex2f(20 * 0.91, 10 * 0.9);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(20 * 0.91, 40 * 0.9);
glVertex2f(20 * 0.91, 0 * 0.9);
glVertex2f(0 * 0.9, 20 * 0.9);
glEnd();
glPopMatrix();
glEndList();

//————————————————————————————————
//| GAME介面的上下左右: |
//————————————————————————————————
glNewList(GAME_Up, GL_COMPILE);//上
glColor3f(0.0, 1.0, 0.0);
//外層
glBegin(GL_POLYGON);
glVertex2f(15, 0);
glVertex2f(35, 0);
glVertex2f(35, 20);
glVertex2f(15, 20);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(50, 20);
glVertex2f(25, 40);
glVertex2f(0, 20);
glEnd();
glEndList();

glNewList(GAME_Down, GL_COMPILE);//下
glColor3f(0.0, 1.0, 0.0);
//外層
glBegin(GL_POLYGON);
glVertex2f(15, 40);
glVertex2f(35, 40);
glVertex2f(35, 20);
glVertex2f(15, 20);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(50, 20);
glVertex2f(25, 0);
glVertex2f(0, 20);
glEnd();
glEndList();

glNewList(GAME_Right, GL_COMPILE);//右
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(0, 10);
glVertex2f(0, 30);
glVertex2f(20, 30);
glVertex2f(20, 10);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(20, 40);
glVertex2f(20, 0);
glVertex2f(40, 20);
glEnd();
glEndList();

glNewList(GAME_Left, GL_COMPILE);//左
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(40, 10);
glVertex2f(40, 30);
glVertex2f(20, 30);
glVertex2f(20, 10);
glEnd();
glBegin(GL_POLYGON);
glVertex2f(20, 40);
glVertex2f(20, 0);
glVertex2f(0, 20);
glEnd();
glEndList();
}

UI設置到這裡就大功告成搂!

完整程式碼在: Github-UI%E8%A8%AD%E8%A8%88)


>