使用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();
}