OpenGL游戏制作之路[第一篇 游戏控件之窗体]---2D游戏---(注:此版本作者处于探索阶段,希望能得到读者的指教和建议)

时间:2024-03-15 15:32:47

前言(重点,考试要考)     

 有的时候,想把一件事情完完整整的做完,但是又不知道背后的动力何在,我发现,写写博客还是能激励自己做下去的,不知道最后能获得什么,但是至少看到了博客数目多起来了,阅读量多起来了,自己的努力有了可视的收获,心里着实踏实不少。这其中也包含着我一直以来都想做的事情,就是自己写一个游戏,不管什么游戏,像样点就行,我琢磨了好久,用什么工具来写(C++还是JAVA还是U3D等等),最后我在DirectX和OpenGL之间开始抉择,可能是本人有点愚笨,U3D愣是没上手明白,感觉不太适应,倒是OpenGL和DX用着比较舒服,后来经过查询资料,发现OpenGL好像可以跨平台,DirectX似乎只能在windows下,或者说是微软那套东西下(应该还有xbox360什么的),我一想,只能在windows下多不爽,那就OpenGL吧,那时我还对OpenGL一无所知,真的,因为刚开始我还在天真的去找什么OpenGL库或者源码去编译,可是后来我发现,哪里是什么库啊,就是一个图形接口,人家早就在显卡驱动里实现了,我需要一些辅助的库去调用和建立环境,就这样我开始学习,发现入了坑,这东西完全没有想象中容易上手,光是乱七八糟的状态机一般的机制就让我着实摸不到头脑,不过经过一段艰辛的探索和适应,我终于能用其写出可以运行的程序了(^_^),就这样,我带着探索和分享的精神,来完成此系列的博客(此处有BGM:HandClap)。

进入正题

这篇系列有些奇怪,因为我一上来就讲如何制作按钮,没有直接进入游戏制作,原因是我只是觉得,我想从这里开始写,毕竟这些东西的写法又没有个规定和条条框框,随意喜欢怎么写就怎么写了,对了看我的博客最好一个字一个字的看,看的太快可能会遗漏什么重要信息。游戏中肯定要使用各种控件,最基本的就是按钮了,这个控件实现了别的也都差不多,因为我之前没有写个游戏,所以看着各种游戏里面花花绿绿的按钮我个人觉得应该不是MFC和Qt那样直接拖上去的按钮,虽然配合OpenGL使用的控件有现成写好的,但是既然已经到了这一步,都没用U3D了,干脆就啥也别用了,白手起家更扎实。还有,要先配置好GLFW,GLEW,GLM。写按钮之前,我们先从基本的窗体开始。

这里面肯定会涉及GL部分的代码,如果没有接触过GL的,我这里也不会说让你单独去学了,我会在相应的地方小小的展开说明一下相关知识的。由于本人写代码功夫仍然需要提升,所以思前想后,还是决定选择C++写能容易一些。我在windows下写代码,用的是CodeLite,用什么IDE读者可以根据自己的喜好,操作系统的话我目前没有在linux和mac(没有mac电脑。。)下试验代码和环境,所以需要自己探索一下了。(补充:拿魔塔游戏来作为开发目标)

创建一个新的GL项目

新建一个OpenGL空白程序,我封装了一个GLWindow类,这个类中包含的就是创建窗体的流程。我设置成了抽象类,目的是方便在上面添加各种新的功能,从而不影响大局的设计思想,因为最后写好游戏后,一个简单的游戏框架也随之成型。代码下载会附在后面。

class GLWindow
{
protected:
	GLFWwindow * window;
	//窗口设置函数,可以继承
	virtual void WindowSetting()=0;
	//设置回调函数
	virtual void SetCallBack()=0;
	//鼠标按键回调函数
	virtual void mouse_buttoncallback(GLFWwindow* window, int button, int action, int mods)=0;
	//鼠标移动回调函数
	virtual void mouse_movecallback(GLFWwindow* window, double xpos, double ypos)=0;
public:
	GLWindow();
	//创建窗口
	bool CreateGLWindow(const char * name,unsigned long window_width,unsigned long window_height,unsigned long view_width,unsigned long view_height);
	//窗口循环渲染
	virtual void Run()=0;
	~GLWindow();
};

 

类就是这个样子,需要键盘事件函数可以再加上,但是目前不需要。

这里对CreateGLWindow函数进行了实现。其中WindowSetting是我们自己写的函数。

bool GLWindow::CreateGLWindow(const char * name,unsigned long window_width,unsigned long window_height,unsigned long view_width,unsigned long view_height)
{
	//初始化glfw
	glfwInit();
	//窗口设置
	WindowSetting();
	//创建一个窗口
	window = glfwCreateWindow(window_width, window_height, name, nullptr, nullptr);
	if(window == nullptr)
		return false;
	//设置窗口上下文
	glfwMakeContextCurrent(window);
	
	//glew初始化
	if (glewInit() != GLEW_OK)
		return false;
	//设置视觉范围
	glViewport(0, 0, view_width, view_height);
	SetCallBack();
	cout << glGetString(GL_VERSION) << endl;
	cout << glGetString(GL_RENDERER) << endl;
}

这个类是抽象类,不能实例化,所以我们需要创建一个继承它的类,GameWindow

class GameWindow : public GLWindow
{
public:
	GameWindow();
	//窗口设置
	virtual void WindowSetting();
	virtual void SetCallBack();
	//运行
	virtual void Run();
	//渲染函数
	//void Render();
	//鼠标按键回调函数
	virtual void mouse_buttoncallback(GLFWwindow* window, int button, int action, int mods);
	//鼠标移动回调函数
	virtual void mouse_movecallback(GLFWwindow* window, double xpos, double ypos);
	~GameWindow();
};

 

这里只是写了暂时需要用的几个函数。后面我们会有更多的。先将WindowSetting函数实现,Run函数实现

void GameWindow::WindowSetting()
{
	//设置OpenGL版本
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//OPENGL核心模式
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
	//窗口大小不可调整
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
}

void GameWindow::Run()
{
	while(!glfwWindowShouldClose(window))
	{
			//渲染等函数
			cout<<"I am running"<<endl;
	}
}

main函数很简单。以后我们的main函数几乎不会有什么变动。

int main()
{
	GameWindow window;
	window.CreateGLWindow("GL",800,600,800,600);
	window.Run();
	return 0;
}

运行的效果就是窗口什么都不显示,一片白色,控制台输出I am runing 。现在渲染处什么都没写,也没有窗口响应函数,所以我们的窗口处于未响应状态,关掉控制台就都关掉了。

OpenGL游戏制作之路[第一篇 游戏控件之窗体]---2D游戏---(注:此版本作者处于探索阶段,希望能得到读者的指教和建议)
运行结果

结束语

这部分是封装好一个GL窗口类,后面我们还会封装更多的东西,下一篇就是封装按钮。

源代码

本篇的源代码下载地址

本次的全部源码都在这里。