opengl小游戏

使用opengl写点小游戏。原理和实现在b站上传了视频,仅在这里放出源码

Game类声明

#pragma once
#include
#include"SOIL.h"
#include
#include
#include
#include

#pragma comment(lib, "SOIL.lib")

GLuint CreateTexture(const char* imgFileName);   // 创建纹理的函数

enum MouseButton
{
	LEFT,
	RIGHT
};

struct MouseEvent
{
	int x, y; // 位置
	bool state;
	MouseButton mouseButton;

	MouseEvent()
	{
		state = false; // 未被点击
	}
};

extern MouseEvent mouseEvent;

class Game
{
	virtual void InitGame() {};
	virtual void PlayGame() {};
	virtual void GameOver() {};
};

class SaoLei : public Game
{
public:
	void InitGame();
	void PlayGame();
	void GameOver();

	SaoLei();
	bool gameOver;

private:
	int leiQu[12][12];
	GLuint* mTexture;           // 共11个纹理。  0~8  雷 棋子
	int GetLeiNum(int x, int y);
	bool clicked[10][10];
};

class Wuziqi : public Game
{
public:
	void InitGame();
	void PlayGame();
	/*
	胜负判断
	@param int x, 当前落子的x索引
	@param int y, 当前落子的y索引
	@param int value, 当前索引下数组的值
	*/
	void GameOver(int x, int y, int value);

	Wuziqi();
	bool gameOver;

private:
	int qiPan[15][15];
	bool blackPlay;

	/*
	画圆,用于棋盘上点的绘制以及棋子的绘制
	@param int x, 圆心x坐标
	@param int y, 圆心y坐标
	@param float radius, 半径
	*/
	void drawCircle(int x, int y, float radius);

};

Game类实现

#include"game.h"

static std::default_random_engine engine(time(0));
static std::uniform_int_distribution num(1, 10);
const int MAX_LEINUM = 10;
const float pi = 3.14159;

GLuint CreateTexture(const char* imgFileName)   // 创建纹理的函数
{
	return SOIL_load_OGL_texture(imgFileName, 0, 0, SOIL_FLAG_POWER_OF_TWO);
}

int SaoLei::GetLeiNum(int x, int y)      // 得到雷区索引为 x,y的周围雷的数量
{
	int count = 0;
	for (int i = -1; i <= 1; ++i)
	{
		for (int j = -1; j <= 1; ++j)
		{
			if (leiQu[x + i][y + j] == 9)
				count++;
		}
	}

	return count;
}

SaoLei::SaoLei()
{
	for (int i = 0; i < 12; ++i)
	{
		for (int j = 0; j < 12; ++j)
		{
			leiQu[i][j] = 0;
		}
	}

	mTexture = new GLuint[11];

	char name[16];
	for (int i = 0; i < 9; ++i)
	{
		memset(name, 0, 16);
		sprintf(name, "Res/扫雷/%d.jpg", i);
		mTexture[i] = CreateTexture(name);
	}
	mTexture[9] = CreateTexture("Res/扫雷/雷.jpg");
	mTexture[10] = CreateTexture("Res/扫雷/over.jpg");

	for (int i = 0; i < 10; ++i)
	{
		for (int j = 0; j < 10; ++j)
		{
			clicked[i][j] = false;
		}
	}

	gameOver = false;
}

void SaoLei::InitGame()
{
	int count = 0;
	int x, y;
	while (count <= MAX_LEINUM)
	{
		x = num(engine);
		y = num(engine);

		if (leiQu[x][y] == 0)
		{
			leiQu[x][y] = 9;           // 雷
			count++;
		}
	}

	for (int i = 1; i < 11; ++i)
	{
		for (int j = 1; j < 11; ++j)
		{
			if (leiQu[i][j] != 9)
			{
				leiQu[i][j] = GetLeiNum(i, j);
			}
		}
	}

	//for (int i = 1; i < 11; ++i)
	//{
	//	for (int j = 1; j < 11; ++j)
	//	{
	//		printf("%4d", leiQu[i][j]);
	//	}
	//	printf("\n\n");
	//}
}

void SaoLei::PlayGame()
{
	for (int i = 1; i < 11; ++i)
	{
		for (int j = 1; j < 11; ++j)
		{
			if (!clicked[i - 1][j - 1])  // 未被点击
			{
				glDisable(GL_TEXTURE_2D);
				glColor3ub(100, 100, 240);  //蓝色填充
				glRectf((i - 1) * 40 + 0.8, (j - 1) * 40 + 0.8 , i * 40 - 0.8 , j * 40 - 0.8);
			}

			else if (clicked[i - 1][j - 1])
			{
				glColor3ub(255, 255, 255);   // 贴图
				glEnable(GL_TEXTURE_2D);
				glBindTexture(GL_TEXTURE_2D, mTexture[leiQu[i][j]]);
				glBegin(GL_QUADS);
				glTexCoord2f(0.0f, 0.0f); glVertex2f((i - 1) * 40, j * 40);
				glTexCoord2f(1.0f, 0.0f); glVertex2f(i  * 40, j * 40);
				glTexCoord2f(1.0f, 1.0f); glVertex2f(i * 40, (j-1) * 40);
				glTexCoord2f(0.0f, 1.0f); glVertex2f((i - 1) * 40, (j - 1) * 40);
				glEnd();
			}
		}
	}

	// 交互
	if (mouseEvent.mouseButton == LEFT && mouseEvent.state) // 左键摁下交互
	{
		mouseEvent.state = false;

		int x, y;
		x = mouseEvent.x / 40 + 1;
		y = mouseEvent.y / 40 + 1;
		clicked[x - 1][y - 1] = true;

		if (leiQu[x][y] == 9)
			GameOver();
		
		// 遍历所有clicked 如果 全部为true 则over

	}
}

void SaoLei::GameOver()
{
	gameOver = true;
	glColor3ub(255, 255, 255);
	glEnable(GL_TEXTURE_2D);

	glBindTexture(GL_TEXTURE_2D, mTexture[10]);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
	glTexCoord2f(1.0f, 0.0f); glVertex2f(400.0f, 0.0f);
	glTexCoord2f(1.0f, 1.0f); glVertex2f(400.0f, 400.0f);
	glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 400.0f);
	glEnd();

}

void Wuziqi::InitGame()
{
}

void Wuziqi::PlayGame()
{
	const int pointSize = 5;
	const int qiziSize = 11;

	// 整个棋盘绘制 // 不贴图了
	glColor3ub(244, 170, 30);
	glBegin(GL_QUADS);
	glVertex2f(10, 10);
	glVertex2f(390, 10);
	glVertex2f(390, 390);
	glVertex2f(10, 390);
	glEnd();

	// 绘制棋盘线
	glLineWidth(2);
	glColor3ub(10, 10, 10);
	glBegin(GL_LINES);
	for (int i = 0; i < 15; ++i)
	{
		glVertex2f(25, (i + 1) * 25);
		glVertex2f(375, (i + 1) * 25);

		glVertex2f((i + 1) * 25, 25);
		glVertex2f((i + 1) * 25, 375);
	}
	glEnd();

	// 绘制棋盘上的点
	drawCircle(4 * 25, 4 * 25, pointSize);
	drawCircle(4 * 25, 12 * 25, pointSize);
	drawCircle(12 * 25, 4 * 25, pointSize);
	drawCircle(12 * 25, 12 * 25, pointSize);
	drawCircle(8 * 25, 8 * 25, pointSize);


	if (mouseEvent.mouseButton == LEFT && mouseEvent.state == true)
	{
		unsigned int x, y;
		x = (mouseEvent.x - 12.5) / 25;
		y = (mouseEvent.y - 12.5) / 25;

		y = 14 - y;

		// 如果该位置的棋盘未被落子,即对应数组值为0,可落子
		if (qiPan[x][y] == 0)
		{
			if (blackPlay)   // 落黑子
			{
				qiPan[x][y] = -1;

				blackPlay = false;
				mouseEvent.state = false;
				GameOver(x, y, -1);
			}
			else if (!blackPlay)   // 落白子
			{
				qiPan[x][y] = 1;

				blackPlay = true;
				mouseEvent.state = false;
				GameOver(x, y, 1);
			}
		}
	}


	// 绘制棋子
	for (int i = 0; i < 15; ++i)
	{
		for (int j = 0; j < 15; ++j)
		{
			if (qiPan[i][j] == 1)
			{
				glColor3f(0.9, 0.9, 0.9);
				drawCircle((i + 1) * 25, (15 - j) * 25, qiziSize);
			}
			else if (qiPan[i][j] == -1)
			{
				glColor3ub(10, 10, 10);
				drawCircle((i + 1) * 25, (15 - j) * 25, qiziSize);
			}
		}
	}





}

void Wuziqi::GameOver(int x, int y, int value)
{
	int startLength, endLength;
	int count = 0; 
	int min, max;

	// 左右判断
	startLength = x >= 4 ? 4 : x;
	endLength = 14 - x >= 4 ? 4 : 14 - x;
	for (int i = 0; i <= startLength + endLength; ++i)
	{
		if (qiPan[x - startLength + i][y] == value)
			count++;
		else
			count = 0;

		if (count >= 5)
		{
			gameOver = true;
	
			if (value == -1)
			{
				printf("黑子 胜!\n");
			}
			else if (value == 1)
			{
				printf("白子 胜!\n");
			}
			return;
		}
	}	

	count = 0;

	// 上下判断
	startLength = y >= 4 ? 4 : y;
	endLength = 14 - y >= 4 ? 4 : 14 - y;
	for (int i = 0; i <= startLength + endLength; ++i)
	{
		if (qiPan[x][y - startLength + i] == value)
			count++;
		else
			count = 0;

		if (count >= 5)
		{
			gameOver = true;			

			if (value == -1)
			{
				printf("黑子 胜!\n");
			}
			else if (value == 1)
			{
				printf("白子 胜!\n");
			}
			return;
		}
	}

	count = 0;

	// 左上 —— 右下 判断
	min = x < y ? x : y;
	max = x > y ? x : y;

	startLength = min >= 4 ? 4 : min;
	endLength = 14 - max >= 4 ? 4 : 14 - max;

	for (int i = 0; i <= startLength + endLength; ++i)
	{
		if (qiPan[x - startLength + i][y - startLength + i] == value)
		{
			count++;
		}
		else
			count = 0;

		if (count >= 5)
		{
			gameOver = true;

			if (value == -1)
			{
				printf("黑子 胜!\n");
			}
			else if (value == 1)
			{
				printf("白子 胜!\n");
			}
			return;
		}
	}

	count = 0;

	// 左下 - 右上判断
	int tempStart1, tempStart2;
	int tempEnd1, tempEnd2;

	tempStart1 = x >= 4 ? 4 : x;
	tempStart2 = 14 - y >= 4 ? 4 : 14 - y;
	startLength = tempStart1 < tempStart2 ? tempStart1 : tempStart2;

	tempEnd1 = 14 - x >= 4 ? 4 : 14 - x;
	tempEnd2 = y >= 4 ? 4 : y;
	endLength = tempEnd1 < tempEnd2 ? tempEnd1 : tempEnd2;

	for (int i = 0; i <= startLength + endLength; ++i)
	{
		if (qiPan[x - startLength + i][y + startLength - i] == value)
		{
			count++;
		}
		else
			count = 0;

		if (count >= 5)
		{
			gameOver = true;

			if (value == -1)
			{
				printf("黑子 胜!\n");
			}
			else if (value == 1)
			{
				printf("白子 胜!\n");
			}
			return;
		}
	}

}

Wuziqi::Wuziqi()
{
	for (int i = 0; i < 15; ++i)
	{
		for (int j = 0; j < 15; ++j)
		{
			qiPan[i][j] = 0; 
		}
	}

	gameOver = false;
	blackPlay = true;
}

void Wuziqi::drawCircle(int x, int y, float radius)
{
	int angle = 0;
	float theta;
	float circleX, circleY;

	glBegin(GL_POLYGON);
	while (angle <= 360)
	{
		theta = angle * pi / 180;        //转化为弧度
		circleX = cos(theta) * radius + x;
		circleY = sin(theta) * radius + y;

		glVertex2f(circleX, circleY);

		angle += 3;
	}
	glEnd();
}

 

你可能感兴趣的:(opengl小游戏)