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

前言(重点,考试要考)     

 有的时候,想把一件事情完完整整的做完,但是又不知道背后的动力何在,我发现,写写博客还是能激励自己做下去的,不知道最后能获得什么,但是至少看到了博客数目多起来了,阅读量多起来了,自己的努力有了可视的收获,心里着实踏实不少。这其中也包含着我一直以来都想做的事情,就是自己写一个游戏,不管什么游戏,像样点就行,我琢磨了好久,用什么工具来写(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 。现在渲染处什么都没写,也没有窗口响应函数,所以我们的窗口处于未响应状态,关掉控制台就都关掉了。

运行结果

结束语

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

源代码

本篇的源代码下载地址

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
作者游戏的说明: 首先,您应当以一种批判的眼光来看待本程序。这个游戏是我制作 的第一部RPG游戏,无任何经验可谈,完全按照自己对游戏的理解进 行设计的。当我参照了《圣剑英雄2》的源码之后,才体会到专业游 戏引擎的博大精深。 该程序的内核大约有2000余行,能够处理人物的行走、对话、战斗, 等等。由于该程序的结构并不适于这种规模的程序,故不推荐您详 细研究该程序。所附地图编辑器的源程序我已经添加了详细的释, 其程序结构也比较合理,可以作为初学VC的例子。 该程序在VC的程序向导所生成的SDI框架的基础上修改而成。它没有 使用任何关于VC底层的东西。程序的绝大部分都是在CgameView类中 制作的,只有修改窗口特征的一段代码在CMainFrm类中。其他的类 统统没有用到。另外添加的一个类是CEnemy类。 整个游戏的故事情节分成8段,分别由Para1.h ~ Para8.h八个文件 实现。由于程序仅仅能够被动的处理各种各样的消息,所以情节的 实现也只能根据系统的一些参数来判断当前应当做什么。在程序中 使用了冗长的if……else if……结构来实现这种判断。 当然,在我的记录本上,详细的记录了每个事件的判断条件。这种 笨拙的设计当然是不可取的。成都金点所作《圣剑英雄II》采用了 剧本解读的方式,这才是正统的做法。但这也需要更多的编程经验 和熟练的code功夫。 下面列举的是程序编制过程中总结出来的经验和教训。 第一,对话方式应该采用《圣剑英雄II》的剧本方式。 现在的方式把一个段落中所有的对话都混在一个文件中,然后给每 句话一个号码相对应。这样做虽然降低了引擎的难度,却导致剧情的 编写极其繁琐。 第二,运动和显示应当完全分开。 现在的程序中,运动和显示是完全同步的。即:在定时器中调用所有 敌人的运动函数,然后将主角的动画向前推一帧,接着绘制地图,调 用所有敌人的显示函数、重绘主角。这样的好处是不会掉帧,但带来 的问题是,如果要提高敌人的运动速度,那么帧数也跟着上去了。所 以当DEMO版反馈说速度太慢的时候,我修改起来非常困难。而这个问 题到最后也仅仅是将4步一格该成了2步一格。 第三,VC中数组存在上限。如果用“int aaa[1000000000]”定义一个 数组,编译器肯定不会给分配那么大的内存空间。而在这个程序中, 地图矩阵、NPC矩阵都超过了VC中数组的上限。但这一点知道的太晚了。 在1.0版本中已经发现地图最右端缺少了几行,但不知道是什么原因 造成的。(地图编辑器中未出现此问题,因为地图编辑器是用“序列 化”的方式存盘读盘的。)解决这个问题的方法是用“new”来分配 内存空间。 第四,由于不知道应该如何使用“new”和“delete”,几乎所有的DC 都使用了全局变量。这是完全没有必要的。程序运行期大约会耗用20 多M的内存空间,相当于一个大型游戏所使用的内存空间了。 另外,在游戏的剧情、美工方面也有许多问题,总之一个词“业余”。 我就不总结了。下一部作品,我将争取在程序上有一个质的飞跃。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值