⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snakessubsonicview.cpp

📁 用opengl编写的简单贪吃蛇游戏
💻 CPP
字号:
// SnakesSubsonicView.cpp : implementation of the CSnakesSubsonicView class
//

#include "stdafx.h"
#include "SnakesSubsonic.h"

#include "SnakesSubsonicDoc.h"
#include "SnakesSubsonicView.h"
#include <math.h>
#include "bitmap.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSnakesSubsonicView
#define interval 100
#define pi 3.1416

IMPLEMENT_DYNCREATE(CSnakesSubsonicView, CView)

BEGIN_MESSAGE_MAP(CSnakesSubsonicView, CView)
	//{{AFX_MSG_MAP(CSnakesSubsonicView)
	ON_WM_DESTROY()
	ON_WM_SIZE()
	ON_WM_KEYDOWN()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSnakesSubsonicView construction/destruction

CSnakesSubsonicView::CSnakesSubsonicView()
{
	// TODO: add construction code here

}

CSnakesSubsonicView::~CSnakesSubsonicView()
{

}

/////////////////////////////////////////////////////////////////////////////
// CSnakesSubsonicView printing

BOOL CSnakesSubsonicView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CSnakesSubsonicView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CSnakesSubsonicView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CSnakesSubsonicView diagnostics

#ifdef _DEBUG
void CSnakesSubsonicView::AssertValid() const
{
	CView::AssertValid();
}

void CSnakesSubsonicView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CSnakesSubsonicDoc* CSnakesSubsonicView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSnakesSubsonicDoc)));
	return (CSnakesSubsonicDoc*)m_pDocument;
}
#endif //_DEBUG

BOOL CSnakesSubsonicView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs
	//设置窗口类型:
	cs.style |= WS_CLIPSIBLINGS|WS_CLIPCHILDREN;

	return CView::PreCreateWindow(cs);
}

void CSnakesSubsonicView::OnInitialUpdate(){
	CView::OnInitialUpdate();
	PIXELFORMATDESCRIPTOR pfd;
	int n;
	HGLRC hrc;
	m_pDC=new CClientDC(this);
	ASSERT(m_pDC!=NULL);
	if(!bSetupPixelFormat())
		return;
	n=::GetPixelFormat(m_pDC->GetSafeHdc());
	::DescribePixelFormat(m_pDC->GetSafeHdc(),n,sizeof(pfd),&pfd);
	// CreateRGBPalette();
	hrc=wglCreateContext(m_pDC->GetSafeHdc());
	wglMakeCurrent(m_pDC->GetSafeHdc(),hrc);
	glEnable(GL_LINE_SMOOTH);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glLineWidth(5.0);
	glShadeModel(GL_FLAT);
	glClearColor(0.0,0.0,0.0,0.0);
	glDepthFunc(GL_LESS);
	glEnable(GL_DEPTH_TEST);

	LoadBMP("pic/bg4.bmp",TextureImage[0]);
	LoadT16("pic/tree.bmp",TextureImage[1]);

	LoadT16("pic/snakehead.bmp",headimage);

	LoadT16("pic/apple.bmp",fruit[0]);
	LoadT16("pic/banana.bmp",fruit[1]);
	LoadT16("pic/blueberry.bmp",fruit[2]);
	LoadT16("pic/lemon.bmp",fruit[3]);
	LoadT16("pic/orange.bmp",fruit[4]);
	LoadT16("pic/pineapple.bmp",fruit[5]);
	LoadT16("pic/pear.bmp",fruit[6]);

	Font = new CGLFont();
	hFont = CreateFont(-108,0,0,0,400,0,0,0,GB2312_CHARSET,0,0,0,FF_MODERN,"Arial");
//	SetTimer(1,interval,NULL);
//	timer = 1;
	GameOver = 0;
}

BOOL CSnakesSubsonicView::bSetupPixelFormat()	//设置像素格式
{
	PIXELFORMATDESCRIPTOR pfd = {
			sizeof(PIXELFORMATDESCRIPTOR),	// pfd结构的大小 
			1,                                // 版本号 
			PFD_DRAW_TO_WINDOW |              // 支持在窗口中绘图 
			PFD_SUPPORT_OPENGL |              // 支持 OpenGL 
			PFD_DOUBLEBUFFER,                 // 双缓存模式 
			PFD_TYPE_RGBA,                    // RGBA 颜色模式 
			24,                               // 24 位颜色深度 
			0, 0, 0, 0, 0, 0,                 // 忽略颜色位 
			0,                                // 没有非透明度缓存 
			0,                                // 忽略移位位 
			0,                                // 无累加缓存 
			0, 0, 0, 0,                       // 忽略累加位 
			32,                               // 32 位深度缓存     
			0,                                // 无模板缓存 
			0,                                // 无辅助缓存 
			PFD_MAIN_PLANE,                   // 主层 
			0,                                // 保留 
			0, 0, 0                           // 忽略层,可见性和损毁掩模 
	};
	int pixelformat;
	if((pixelformat=ChoosePixelFormat(m_pDC->GetSafeHdc(),&pfd))==0)
	{
		MessageBox("choosepixelformated failed");
		return false;
	}
	if(SetPixelFormat(m_pDC->GetSafeHdc(),pixelformat,&pfd)==FALSE)
	{
		MessageBox("SetPixelFormat failed");
		return false;
	}
	return true;
}

/////////////////////////////////////////////////////////////////////////////
// CSnakesSubsonicView drawing

void CSnakesSubsonicView::OnDraw(CDC* pDC)
{
	KillTimer(1);
	timer = 0;

	CSnakesSubsonicDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

 	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);				// 设置刷新背景色
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);	// 刷新背景
	
	if(GameOver){
		glTranslatef(0,0,-4);	// 背景图片位置
		CString gover = "Game Over";
		Font->entext(-1.5, 0, gover, hFont, 1.0f, 0.0f, 1.0f);
	}
	else{
		snk.DrawHead(headimage);
		snk.DrawSnake();
		
//	LoadT16("pic/apple.bmp",fruit[0]);
// 	LoadT16("pic/banana.bmp",fruit[1]);
// 	LoadT16("pic/apple1.bmp",fruit[2]);
// 	LoadT16("pic/lemon.bmp",fruit[3]);
// 	LoadT16("pic/orange.bmp",fruit[4]);
// 	LoadT16("pic/pineapple.bmp",fruit[5]);
// 	LoadT16("pic/pear.bmp",fruit[6]);

		switch(snk.foodkind){
			case 0:
				snk.DrawFood(fruit[0],0.6,0.6);
				break;
			case 1:
				snk.DrawFood(fruit[1],0.7,0.42);
				break;
			case 2:
				snk.DrawFood(fruit[2],0.6,0.4);
				break;
			case 3:
				snk.DrawFood(fruit[3],0.6,0.6);
				break;
			case 4:
				snk.DrawFood(fruit[4],0.6,0.65);
				break;
			case 5:
				snk.DrawFood(fruit[5],0.6,0.6);
				break;
			case 6:
				snk.DrawFood(fruit[6],0.6,0.6);
				break;
		}

	}

	glLoadIdentity();									// 重置当前的模型观察矩阵

	float height = 7.68;	// 背景图片尺寸
	float width = 10.24;
	
//	LoadBMP("pic/bg4.bmp",TextureImage[0]);

	glPushMatrix();
		glColor4f(1,1,1,1);		// 设置背景贴图底色为白色
	
		glTranslatef(0,0,-5);	// 背景图片位置
	
		glBindTexture(GL_TEXTURE_2D, TextureImage[0]);	// This Will Select The BG Maps...

		glEnable(GL_TEXTURE_2D);
//		glPushMatrix();
			glBegin(GL_QUADS);
//				glNormal3f( 0.0f, 0.0f, 1.0f);	//设置传递参数的当前法线
				glTexCoord2f(0.0f, 0.0f); glVertex2f( -width/2,  -height/2);		
				glTexCoord2f(1.0f, 0.0f); glVertex2f(  width/2,  -height/2);
				glTexCoord2f(1.0f, 1.0f); glVertex2f(  width/2,   height/2);
				glTexCoord2f(0.0f, 1.0f); glVertex2f( -width/2,   height/2);
			glEnd();

		glDisable(GL_TEXTURE_2D);
	glPopMatrix();

	DrawBorderTree();

	glFinish();									// 更新窗口

	DrawIcon(pDC->m_hDC,0,0,(HICON)IDI_Acorn);
//	glDisable(GL_LIGHT0);
//	glDisable(GL_LIGHTING);



//	snk.SnakeRun();
 
	SwapBuffers(wglGetCurrentDC());				// 切换缓冲区 只能在最后一次

	if(!timer){
		SetTimer(1,interval,NULL);
		timer = 1;
	}
}

void CSnakesSubsonicView::DrawBorderTree(){
// 	RECT border;
// 	GetWindowRect(&border);
// 	long left = border.left;
// 	long top = border.top;

	double height = 0.33;	// 图片尺寸
	double width = 0.28;

	float inc = 0.2;
	if (isOnSize)
	{	
		if(AfxGetMainWnd()->IsZoomed()){
			glw += 1.6;
			glh += 1.1;
		}
		else{
			glw += 1.9;
			glh += 1.2;
		}
		isOnSize = 0;
	}


	glPushMatrix();

	glColor4f(1,1,1,1);		// 设置背景贴图底色为白色

	glTranslatef(-glw-inc,glh,-4.9);	// 起始位置 (-3.1, 2)
	
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER, 0);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, TextureImage[1]);	// This Will Select The BG Maps...
	
	glEnable(GL_TEXTURE_2D);

	for (int i=0;i<2*glw/inc;i++)
	{		
		glTranslatef(inc,0,0);	// 相对位移
			glBegin(GL_QUADS);
				glTexCoord2d(0.0f, 0.0f); glVertex2d( -width/2,  -height/2);		
				glTexCoord2d(1.0f, 0.0f); glVertex2d(  width/2,  -height/2);
				glTexCoord2d(1.0f, 1.0f); glVertex2d(  width/2,   height/2);
				glTexCoord2d(0.0f, 1.0f); glVertex2d( -width/2,   height/2);
			glEnd();
		glTranslatef(0,-2*glh,0);	// 相对位移
			glBegin(GL_QUADS);
				glTexCoord2d(0.0f, 0.0f); glVertex2d( -width/2,  -height/2);		
				glTexCoord2d(1.0f, 0.0f); glVertex2d(  width/2,  -height/2);
				glTexCoord2d(1.0f, 1.0f); glVertex2d(  width/2,   height/2);
				glTexCoord2d(0.0f, 1.0f); glVertex2d( -width/2,   height/2);
			glEnd();
		glTranslatef(0,2*glh,0);	// 相对位移

	}
	
// 	if (AfxGetMainWnd()->IsZoomed())
// 	{
// 		glTranslatef(-0.5,0,0);	// 相对位移
// 	}

	for (i=0;i<2*glh/inc-1;i++)
	{
		glTranslatef(0,-inc,0);	// 相对位移
			glBegin(GL_QUADS);
				glTexCoord2d(0.0f, 0.0f); glVertex2d( -width/2,  -height/2);		
				glTexCoord2d(1.0f, 0.0f); glVertex2d(  width/2,  -height/2);
				glTexCoord2d(1.0f, 1.0f); glVertex2d(  width/2,   height/2);
				glTexCoord2d(0.0f, 1.0f); glVertex2d( -width/2,   height/2);
			glEnd();
		glTranslatef(-2*glw,0,0);	// 相对位移
			glBegin(GL_QUADS);
				glTexCoord2d(0.0f, 0.0f); glVertex2d( -width/2,  -height/2);		
				glTexCoord2d(1.0f, 0.0f); glVertex2d(  width/2,  -height/2);
				glTexCoord2d(1.0f, 1.0f); glVertex2d(  width/2,   height/2);
				glTexCoord2d(0.0f, 1.0f); glVertex2d( -width/2,   height/2);
			glEnd();
		glTranslatef(2*glw,0,0);	// 相对位移
	}

	glDisable(GL_TEXTURE_2D);
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_BLEND);

	glPopMatrix();
}

void CSnakesSubsonicView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here

	//cx,cy是client尺寸
	sw = cx;						//屏幕宽度
	sh = cy;						//屏幕高度

	if(sh==0) sh=1;
	glViewport(0,0,sw,sh);			// 设置OpenGL视口大小。	
	glMatrixMode(GL_PROJECTION);	// 设置当前矩阵为投影矩阵。
	glLoadIdentity();				// 重置当前指定的矩阵为单位矩阵
	gluPerspective(					// 设置透视图
		60,							// 透视角设置为 60 度
		(GLfloat)sw/(GLfloat)sh,	// 窗口的宽与高比
		1.0,						// 视野透视深度:近点1.0f
		10							// 视野透视深度:始点1.0f远点10.0f
		);
	// 这和照象机很类似,第一个参数设置镜头广角度,第二个参数是长宽比,后面是远近剪切。
	glMatrixMode(GL_MODELVIEW);		// 设置当前矩阵为模型视图矩阵
	glLoadIdentity();				// 重置当前指定的矩阵为单位矩阵
	
	gluLookAt(0,0,0,0,0,1,0,1,0);
	
	glRect(4,60.0);

	isOnSize = 1;
//	glDrawBuffer (GL_BACK);			// 告诉OpenGL在后台缓存中画图
}

void CSnakesSubsonicView::glRect(double l, double fovy){
	double ratio = sh/sw;
	double d = fovy/360*pi;
	glw = l*tan(d);
	glh = glw*ratio;
}

void CSnakesSubsonicView::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	switch(nIDEvent){
	case 1 :
		snk.SnakeRun(glw,glh);

		if(snk.isDead()){
//			AfxMessageBox("你挂了!");
			KillTimer(1);
			GameOver = 1;
//			break;
		}
		
		Invalidate(FALSE);							// 刷新屏幕
		
		break;
	}
	CView::OnTimer(nIDEvent);
}

void CSnakesSubsonicView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
//	KillTimer(1);
	timer = 0;
	
	if(nChar ==VK_LEFT && (snk.snk_MD == snk.snk_up || snk.snk_MD == snk.snk_down))
		snk.snk_MD = snk.snk_left;      
	
	if(nChar == VK_RIGHT && (snk.snk_MD == snk.snk_up || snk.snk_MD == snk.snk_down))	
		snk.snk_MD = snk.snk_right;  
	
    if(nChar == VK_UP && (snk.snk_MD == snk.snk_left || snk.snk_MD == snk.snk_right))
		snk.snk_MD = snk.snk_up;
	
	if(nChar == VK_DOWN && (snk.snk_MD == snk.snk_left || snk.snk_MD == snk.snk_right))
		snk.snk_MD = snk.snk_down;

//	snk.SnakeRun();

//	Invalidate(FALSE);							// 刷新屏幕
}
/////////////////////////////////////////////////////////////////////////////
// CSnakesSubsonicView message handlers

BOOL CSnakesSubsonicView::LoadBMP(char *Filename, GLuint &texture)
{
	FILE *File=NULL;									// File Handle
	AUX_RGBImageRec *pImage = NULL;
	
	if (!Filename)										// Make Sure A Filename Was Given
	{
		return FALSE;									// If Not Return NULL
	}
	
	File=fopen(Filename,"r");							// Check To See If The File Exists
	
	if (File)											// Does The File Exist?
	{
		fclose(File);									// Close The Handle
		pImage = auxDIBImageLoad(Filename);				// Load The Bitmap And Return A Pointer
	}
	
	if(pImage == NULL)	
		return FALSE;
	
	glGenTextures(1, &texture);	
	glBindTexture    (GL_TEXTURE_2D,texture);
	gluBuild2DMipmaps(GL_TEXTURE_2D,4, pImage->sizeX, 
		pImage->sizeY,GL_RGB, GL_UNSIGNED_BYTE,pImage->data);
	
	free(pImage->data);
	free(pImage);	
	return TRUE;
}

void CSnakesSubsonicView::LoadT16(char *filename, GLuint &texture)
{ 
	glGenTextures(1, &texture);  
	glBindTexture(GL_TEXTURE_2D, texture);
	BITMAPINFOHEADER bitHeader;
	unsigned char *buffer;  
	buffer=LoadBitmapFileWithAlpha(filename,&bitHeader);
	gluBuild2DMipmaps( 
		GL_TEXTURE_2D,  
		4,    
		bitHeader.biWidth, 
		bitHeader.biHeight,
		GL_RGBA, 
		GL_UNSIGNED_BYTE,
		buffer  
	); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
	free(buffer);  
}

void CSnakesSubsonicView::OnDestroy() 
{
	CView::OnDestroy();
	
	// TODO: Add your message handler code here
	HGLRC hrc;
	// KillTimer(1);
	hrc=::wglGetCurrentContext();
	::wglMakeCurrent(NULL,NULL);
	if(hrc)
		::wglDeleteContext(hrc);
	if(m_pDC)
	delete m_pDC;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -