OpenGL實現貪吃蛇程式碼
OpenGL實現貪吃蛇程式碼
#include <cassert>
#include <cstdlib>
#include <ctime>
#include <GL/glut.h> // Header File For The GLUT Library
#include <GL/gl.h> // Header File For The OpenGL32 Library
#include <GL/glu.h> // Header File For The GLu32 Library
#include <unistd.h> // Header file for sleeping.
/* ascii code for the escape key */
#define ESCAPE 27
/* 大小定義 */
#define ISNAKE_WIDTH 20
#define ISNAKE_HEIGHT 20
/* 方向定義 */
#define DIR_UP 0
#define DIR_DOWN 1
#define DIR_LEFT 2
#define DIR_RIGHT 3
/* 顏色定義(RGB) */
#define CLR_BLACK 0.0f, 0.0f, 0.0f
#define CLR_RED 1.0f, 0.0f, 0.0f
#define CLR_GREEN 0.0f, 1.0f, 0.0f
#define CLR_YELLOW 1.0f, 1.0f, 0.0f
#define CLR_BLUE 0.0f, 0.0f, 1.0f
#define CLR_MEGENTA 1.0f, 0.0f, 1.0f
#define CLR_CYAN 0.0f, 1.0f, 1.0f
#define CLR_WHITE 1.0f, 1.0f, 1.0f
/* 時間加快所要吃到的食物個數 */
#define MIN_FOOD 20
/* 最慢時間,ms */
#define TIME_BASE 300
/* 最塊時間,ms */
#define TIME_MIN 50
/* 每次升級時間縮短單位,ms */
#define TIME_UPUNIT 50
GLenum fillMode = GL_SMOOTH;
int level=0;
typedef struct _RGB{
float r;
float g;
float b;
}RGB;
typedef struct Position{
int x;
int y;
}Pos;
typedef struct _SnakeNode{
int color;
int index_x;
int index_y;
struct _SnakeNode *prev;
struct _SnakeNode *next;
}SnakeNode;
struct _Snake{
SnakeNode *head;
SnakeNode *tail;
int num;
} _snake;
RGB _color[] = {
{ CLR_RED }, { CLR_GREEN } , { CLR_BLUE }, { CLR_YELLOW},
{ CLR_CYAN}, { CLR_MEGENTA}, { CLR_WHITE}, { CLR_BLACK},
};
/* 0, 1, 2, 3分別代表上下左右 */
int _direction = DIR_RIGHT; /* 要控制的方向 */
int _move_dir = DIR_RIGHT; /* 當前移動方向 */
int _dir_x[4] = {-1, 1, 0, 0};
int _dir_y[4] = { 0, 0,-1, 1};
/* 定時時間 */
int _timer = TIME_BASE;
/* 遊戲結束標誌 */
int _finish_flag = 0;
/* 暫停標誌 */
int _pause_flag = 0;
/* 食物座標 */
Pos _food_pos;
int _food_clr_id;
/* The number of our GLUT window */
int window;
int wnd_width;
int wnd_height;
/* 移動,將最後一個節點變為頭節點,根據方向改變座標 */
void SnakeMove(int direction)
{
/* 當前頭部位置 */
int x = _snake.head->index_x;
int y = _snake.head->index_y;
int c = _snake.head->color;
SnakeNode *node = _snake.head;
/* 移動之前改變顏色 */
for ( ; node->next != NULL; node = node->next){
node->color = node->next->color;
}
node->color = c;
/* 將尾巴加到頭部 */
_snake.tail->prev->next = NULL;
_snake.head->prev = _snake.tail;
_snake.tail->next = _snake.head;
_snake.head = _snake.tail;
_snake.tail = _snake.tail->prev;
_snake.head->prev = NULL;
_snake.tail->next = NULL;
/* 方向 */
_snake.head->index_x = x + _dir_x[direction];
_snake.head->index_y = y + _dir_y[direction];
if (_snake.head->index_x < 0) { _snake.head->index_x = ISNAKE_HEIGHT-1; }
if (_snake.head->index_x > ISNAKE_HEIGHT-1) { _snake.head->index_x = 0; }
if (_snake.head->index_y < 0) { _snake.head->index_y = ISNAKE_WIDTH-1; }
if (_snake.head->index_y > ISNAKE_WIDTH-1 ) { _snake.head->index_y = 0; }
_move_dir = _direction;
}
/*
* 判斷遊戲是否結束
*/
int IsFinish(void)
{
int x, y;
SnakeNode *node;
x = _snake.head->index_x + _dir_x[_direction];
y = _snake.head->index_y + _dir_y[_direction];
if(x>=ISNAKE_WIDTH || x<0 || y>=ISNAKE_HEIGHT || y<0){
glutSetWindowTitle(" FINISHED !!");
return 1;
}
for (node = _snake.head->next; node != NULL; node = node->next){
if (node->index_x == x && node->index_y == y){
glutSetWindowTitle(" FINISHED !!");
return 1;
}
}
return 0;
}
/*
* 判斷是否有食物
* 有返回1, 無則返回0
*/
int HasFood(void)
{
SnakeNode *node = _snake.head;
if (node->index_x + _dir_x[_direction] == _food_pos.x
&& node->index_y + _dir_y[_direction] == _food_pos.y
){
return 1;
}
while( node != NULL ){
if (node->index_x == _food_pos.x &&
node->index_y == _food_pos.y){
return 1;
}
node = node->next;
}
return 0;
}
void SnakeEat(int x, int y) //snake eat food
{
SnakeNode *node = (SnakeNode*)malloc(sizeof(SnakeNode));
node->index_x = x;
node->index_y = y;
_snake.head->prev = node;
node->next = _snake.head;
node->prev = NULL;
_snake.head = node;
_snake.num++;
_snake.head->color = _food_clr_id;
}
int CorrectFood(int x, int y) // judge whether the random food is correct
{
SnakeNode *node = _snake.head;
for ( ; node != NULL; node = node->next){
if (node->index_x == x && node->index_y == y){
return 0;
}
}
return 1;
}
void RandomFood(void) //creat food in random color and random position.
{
int x, y;
srand(time(NULL));
do{
x = (double)rand() / RAND_MAX * ISNAKE_HEIGHT-1;
y = (double)rand() / RAND_MAX * ISNAKE_WIDTH-1;
}while(!CorrectFood(x,y));
_food_clr_id = (double)rand() / RAND_MAX * (sizeof(_color)/sizeof(_color[0])-2);
_food_pos.x = x; _food_pos.y = y;
}
/*
* 初始化一個帶有n個方塊的蛇
*/
void SnakeInit(int n)
{
int i;
SnakeNode *node;
_snake.head = _snake.tail = (SnakeNode*)malloc(sizeof(SnakeNode));
_snake.head->index_x = ISNAKE_HEIGHT/2;
_snake.head->index_y = ISNAKE_WIDTH/2;
_snake.head->color = 0;
for (i = 0; i < n-1; ++i){
node = (SnakeNode*)malloc(sizeof(SnakeNode));
node->index_x = _snake.tail->index_x;
node->index_y = _snake.tail->index_y-1;
node->color = (i+1)%7;
node->prev = _snake.tail;
_snake.tail->next = node;
_snake.tail = node;
}
_snake.head->prev = NULL;
_snake.tail->next = NULL;
_snake.num = n;
RandomFood();
_direction = DIR_RIGHT;
}
/*
* OpenGL初始化函式
*/
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluOrtho2D(0.0f,(GLdouble)Width, 0.0f, (GLdouble)Height);
}
/* The function called when our window is resized */
void ReSizeGLScene(int Width, int Height)
{
if (Height==0) // Prevent A Divide By Zero If The Window Is Too Small
Height=1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0f, (GLdouble)Width, 0.0f, (GLdouble)Height);
}
/* The main drawing function. */
void DrawGLScene()
{
int i, j, clr;
static double unit_x = 2.0f/ISNAKE_WIDTH;
static double unit_y = 2.0f/ISNAKE_HEIGHT;
SnakeNode *node = _snake.head;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View (將當前點移到螢幕中心)
glTranslatef(-1.0f, 1.0f, 0.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_QUADS);
glColor3f(CLR_WHITE);
for (i = 0; i < ISNAKE_HEIGHT; ++i){
for (j = 0; j < ISNAKE_WIDTH; ++j){
glVertex3f((j ) * unit_x, -(i ) * unit_y, 0.0f);
glVertex3f((j+1) * unit_x, -(i ) * unit_y, 0.0f);
glVertex3f((j+1) * unit_x, -(i+1) * unit_y, 0.0f);
glVertex3f((j ) * unit_x, -(i+1) * unit_y, 0.0f);
}
}
glEnd();
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glBegin(GL_QUADS);
/* snake */
while(node != NULL){
clr = node->color;
glColor3f(_color[clr].r, _color[clr].g, _color[clr].b);
glVertex3f((node->index_y ) * unit_x, -(node->index_x ) * unit_y, 0.0f);
glVertex3f((node->index_y+1) * unit_x, -(node->index_x ) * unit_y, 0.0f);
glVertex3f((node->index_y+1) * unit_x, -(node->index_x+1) * unit_y, 0.0f);
glVertex3f((node->index_y ) * unit_x, -(node->index_x+1) * unit_y, 0.0f);
node = node->next;
}
/* food */
glColor3f(_color[_food_clr_id].r, _color[_food_clr_id].g, _color[_food_clr_id].b);
glVertex3f((_food_pos.y ) * unit_x, -(_food_pos.x ) * unit_y, 0.0f);
glVertex3f((_food_pos.y+1) * unit_x, -(_food_pos.x ) * unit_y, 0.0f);
glVertex3f((_food_pos.y+1) * unit_x, -(_food_pos.x+1) * unit_y, 0.0f);
glVertex3f((_food_pos.y ) * unit_x, -(_food_pos.x+1) * unit_y, 0.0f);
glEnd();
glutSwapBuffers();
}
/*
* 定時器響應函式
*/
void OnTimer(int value)
{
if (!value && !_pause_flag){
if ( HasFood() ){
SnakeEat(_food_pos.x, _food_pos.y);
RandomFood();
}
if (!IsFinish()){
SnakeMove(_direction);
}else{
_finish_flag = 1;
}
_timer = (TIME_BASE - TIME_UPUNIT*(_snake.num/MIN_FOOD+level));
_timer = _timer > TIME_MIN ? _timer:TIME_MIN;
_timer = _timer > TIME_BASE ? TIME_BASE:_timer;
glutTimerFunc(_timer,OnTimer,_finish_flag);
}
}
/* The function called whenever a key is pressed. */
void keyPressed(unsigned char key, int x, int y)
{
/* avoid thrashing this procedure */
usleep(100);
if (key == ESCAPE) {
glutDestroyWindow(window);
exit(0);
}
switch(key){
case ' ': /* pause */
_pause_flag = !_pause_flag;
if (!_pause_flag){
glutTimerFunc(_timer,OnTimer, _finish_flag);
}
break;
default:
break;
}
}
/*
* 方向鍵
*/
void OnDirection(int key, int x, int y)
{
if (_pause_flag) { return; }
switch(key){
case GLUT_KEY_UP: if (_move_dir != DIR_DOWN) { _direction = DIR_UP; }
break;
case GLUT_KEY_DOWN: if (_move_dir != DIR_UP ) { _direction = DIR_DOWN;}
break;
case GLUT_KEY_LEFT: if (_move_dir != DIR_RIGHT){ _direction = DIR_LEFT;}
break;
case GLUT_KEY_RIGHT:if (_move_dir != DIR_LEFT ){ _direction = DIR_RIGHT;}
break;
default:
break;
}
}
void mainMenu (GLint selectedOption) //main menu
{
switch (selectedOption) {
case 1: glClearColor(0,0,0,0);
break;
case 2: glClearColor(0.5,0.5,0.5,0);
break;
}
glutPostRedisplay ( );
}
void levelSubMenu (GLint levelSubMenu) //submenu to set level.
{
switch (levelSubMenu) {
case 1:
level=1;
break;
case 2:
level=2;
break;
case 3:
level=3;
break;
case 4:
level=4;
break;
case 5:
level=5;
break;
case 6:
level=6;
break;
}
glutPostRedisplay ( );
}
int main(int argc, char **argv)
{
SnakeInit(4);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
window = glutCreateWindow("貪吃蛇");
glutDisplayFunc(&DrawGLScene);
glutIdleFunc(&DrawGLScene);
glutReshapeFunc(&ReSizeGLScene);
glutKeyboardFunc(&keyPressed);
glutSpecialFunc(OnDirection);
glutTimerFunc(_timer, OnTimer, _finish_flag);
InitGL(500, 500);
GLint subMenu;
subMenu= glutCreateMenu (levelSubMenu);
glutAddMenuEntry ("Level 1", 1);
glutAddMenuEntry ("Level 2", 2);
glutAddMenuEntry ("Level 3", 3);
glutAddMenuEntry ("Level 4", 4);
glutAddMenuEntry ("Level 5", 5);
glutAddMenuEntry ("Level 6", 6);
glutCreateMenu (mainMenu); // Create pop-up menu.
glutAddMenuEntry (" Black ", 1);
glutAddMenuEntry (" Gray ", 2);
glutAddSubMenu (" Level ", subMenu);
/* Select a menu option using the right mouse button. */
glutAttachMenu (GLUT_RIGHT_BUTTON);
glutMainLoop();
return 1;
}
相關文章
- Java實現貪吃蛇Java
- canvas實現的貪吃蛇遊戲程式碼例項Canvas遊戲
- python實現貪吃蛇Python
- jQuery 實現貪吃蛇遊戲jQuery遊戲
- 貪吃蛇c原始碼原始碼
- 貪吃蛇源程式 (轉)
- js貪吃蛇遊戲程式碼例項JS遊戲
- canvas貪吃蛇遊戲程式碼例項Canvas遊戲
- C語言實現桌面貪吃蛇C語言
- Python實現貪吃蛇大作戰Python
- js開發實現簡單貪吃蛇遊戲(20行程式碼)JS遊戲行程
- js實現的移動端貪吃蛇遊戲程式碼例項JS遊戲
- 貪吃蛇jsJS
- 04 貪吃蛇
- javascript貪吃蛇小遊戲程式碼例項JavaScript遊戲
- C語言貪吃蛇原始碼C語言原始碼
- [原生JS][程式導向]貪吃蛇JS
- Ubuntu下C語言實現貪吃蛇遊戲UbuntuC語言遊戲
- (完整原始碼)貪吃蛇小遊戲——HTML+CSS+JavaScript實現原始碼遊戲HTMLCSSJavaScript
- 100行Python程式碼實現貪吃蛇小遊戲(超詳細)Python遊戲
- 一個貪吃蛇小遊戲(17行程式碼)遊戲行程
- Python:遊戲:貪吃蛇Python遊戲
- h5+js實現單機版貪吃蛇H5JS
- js+jquery實現貪吃蛇經典小遊戲JSjQuery遊戲
- 純JS實現貪吃蛇遊戲 —— 可能是全網程式碼最優雅的實現。JS遊戲
- 貪吃蛇大作戰JavaFx版完整原始碼Java原始碼
- Python3 貪吃蛇Python
- C#貪吃蛇(WPF版)C#
- WebGL實現HTML5的3D貪吃蛇遊戲WebHTML3D遊戲
- [譯] RxJS 遊戲之貪吃蛇JS遊戲
- Shell寫的貪吃蛇遊戲(轉)遊戲
- 初試javascript :貪吃蛇啊 (轉)JavaScript
- c/c++實現簡單的貪吃蛇視覺化遊戲C++視覺化遊戲
- 無法執行的貪吃蛇遊戲程式碼,求大神幫忙改動!遊戲
- 溫習資料演算法—貪吃蛇演算法
- html畫布製作貪吃蛇小遊戲HTML遊戲
- H5遊戲開發:貪吃蛇H5遊戲開發
- 貪吃蛇的演算法分析(1) (轉)演算法