太空侵略者游戏攻略-第1部分图文攻略

攻略大全 0 419

在本系列文章中,我将使用 C++ 创建经典街机游戏太空入侵者的克隆,仅使用几个依赖项。 在这篇文章中,我将使用 GLFW 和 GLEW 设置一个带有 OpenGL 3.3 上下文的窗口,作为这个简单克隆的唯一依赖项。

太空侵略者

Space Invaders 是一款街机游戏,于 1978 年首次发布。它是一款 2D 水平射击游戏,玩家通过在屏幕底部移动大炮来控制大炮并向一群外星人射击。 每击落一个外星人都会获得积分。 不明飞行物偶尔会在屏幕顶部移动并在被摧毁时奖励积分。 随着越来越多的外星人被击败,游戏速度加快。 外星人在接近屏幕底部时也会随机射击,如果射击击中玩家,他就会失去生命。 大炮部分受到几个掩体的保护,这些掩体被外星人或玩家的无数次爆炸逐渐摧毁。 击败所有外星人带来另一波并修复所有掩体。 如果所有掩体都被摧毁或外星人到达底部,或者玩家失去所有生命,则游戏结束。

设定目标

在开始新项目之前设定目标很重要。我的计划不是忠实地重构原始的太空侵略者游戏,而是制作只有核心元素的太空侵略者类游戏。在游戏开发中也很常见,首先使用您想要测试的核心机制创建一个粗略的原型,然后添加“抛光”。所以计划是创造一个太空入侵者的原型。在这个原型中,我希望玩家控制卡农,逐渐向卡农传播的外星波,最重要的是,能够同时为外星人和卡农射击。因此,我将忽略 UFO 和掩体,但这些很容易实现。

请注意,所有游戏都可以分解为非常基本的元素(我强烈推荐 Raph Koster 的精彩演讲)。在太空入侵者中,可以识别两个基本元素——射击,也可以看作是碰撞检测的一种形式,以及运动。大多数 AAA 游戏都涉及某种射击或碰撞检测以及移动。这些游戏的复杂性来自于混合在一起的数量元素、维度的数量、动作的复杂性以及各种游戏规则。因此,即使是开发一个简单的太空入侵者克隆体,也可以教会我们很多关于游戏和游戏开发的知识。

所以,设定好目标,让我们开始编程吧!

你好窗口

有多种创建窗口的方法。 您可以使用本机 API,例如 Cocoa、X 或 WinAPI,或者您可以使用跨平台库,例如 Qt 或 GLFW。 如果你想完全控制你的代码,你可以选择原生 API 方法,但为了避免头疼并轻松地使这个小项目跨平台,我决定使用 GLFW。 GLFW 是轻量级的,并且有一个简单的 C API。

要使用 GLFW,我们需要包含它的头文件。 除了它,我们还包括标准的 C IO 头文件,

#include<cstdio>#include<GLFW/glfw3.h>

在 GLFW 中创建窗口之前,我们需要能够获取错误事件。 GLFW 中的事件通过回调报告。 错误回调是在 GLFW 中使用函数设置的

GLFWerrorfunglfwSetErrorCallback(GLFWerrorfun cbfun)

回调应具有以下签名,

typedefvoid(*GLFWerrorfun)(int, constchar*)

在第一个参数中它接收错误代码,在第二个参数中它接收错误描述作为 UTF-8 编码字符串。 我们创建一个简单的错误回调,将错误描述打印到 stderr。

voiderror_callback(interror, constchar* description){ fprintf(stderr, "Error: %s\n", description); }

在我们的主函数中,我们将错误回调移交给 GLFW,以便它可以在发生错误时调用它,

glfwSetErrorCallback(error_callback);

我们现在可以开始初始化 GLFW 库了,

if(!glfwInit()) { return-1; }

最后,要创建一个窗口,我们添加以下代码,

window=glfwCreateWindow(640,480,"Space Invaders",NULL,NULL);if(!window){glfwTerminate();return-1;}glfwMakeContextCurrent(window);

这将创建一个标题为“Space Invaders”的窗口,分辨率为 640x480,带有 OpenGL 上下文。 glfwCreateWindow 调用的最后两个参数用于为全屏模式指定监视器,以及在不同窗口之间共享上下文。 如果在创建窗口时出现任何问题,我们调用 glfwTerminate 让 GLFW 销毁其资源。 我们还需要告诉 GFLW 使后续的 OpenGL 调用应用于当前上下文。 我们通过调用 glfwMakeContextCurrent 来做到这一点。 目前我们从 GLFW 收到的 OpenGL 上下文版本是未知的。 我们需要告诉 GLFW 我们想要一个至少是 3.3 版本的上下文。 这是通过在创建窗口之前给 GLFW 适当的“提示”来完成的,

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

与大多数库不同,OpenGL 是一种 API 规范。 实际的 API 实现可能因不同的 GPU 和供应商、操作系统和图形驱动程序而异。 OpenGL 规范定义了许多功能,您的图形驱动程序可能不支持所有功能。 因此,OpenGL 函数需要在运行时显式声明和加载。 虽然我们可以处理我们需要的函数的加载,但通常建议使用加载库。 对于这个项目,我决定使用 GLEW,因为我以前在其他项目中使用过它。 GLEW 头文件需要在 glfw3.h 之前包含,

#include<GL/glew.h>

在使上下文成为当前上下文之后,我们初始化 GLEW,

GLenum err = glewInit(); if(err != GLEW_OK) { fprintf(stderr, "Error initializing GLEW.\n"); glfwTerminate(); return-1; }

在此之后,我们终于可以调用 OpenGL 函数了。 我们先查询我们得到的OpenGL版本,

intglVersion[2] = {-1, 1}; glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]); glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]);printf("Using OpenGL: %d.%d\n", glVersion[0], glVersion[1]);

游戏循环

如果我们运行到目前为止编写的代码,我们很可能什么也看不到。 窗口将被创建,程序将立即退出。 为了保持窗口打开,我们需要创建一个所谓的游戏循环。 游戏循环是处理输入、更新和绘制游戏的无限循环; 它本质上是每场比赛的核心。 游戏循环可能会变得非常复杂,但同样,我会保持简单,

glClearColor(1.0, 0.0, 0.0, 1.0); while(!glfwWindowShouldClose(window)) { glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(window); glfwPollEvents(); }

我们首先将 glClear 的缓冲区清除颜色设置为红色。 在图形编程中,缓冲区是指计算机用来保存临时图像的 RAM 的一部分。 现代 OpenGL 使用双缓冲方案; “前”缓冲区用于显示图像,而“后”缓冲区用于绘图。 然后在每次迭代时交换缓冲区——这就是在这里使用 glfwSwapBuffers 调用完成的。 此外,在每次迭代中,我们通过检查 glfwWindowShouldClose 的返回值指示 GLFW 处理任何未决事件 glfwPollEvents,并在 GLFW 被指示这样做(例如通过单击关闭按钮)时终止无限循环。 此时,如果我们想让我们的程序干净地退出,我们还需要进行以下两个调用,

glfwDestroyWindow(window); glfwTerminate();

编译

这篇文章的完整代码可以在这里找到。 要在 Linux 下使用 g++ 编译它,请在终端上发出以下命令,

g++ -std=c++11-o main -lglfw -lGLEW -lGL main.cpp

在 Mac OS X 上使用 Xcode 命令行工具,

g++ -std=c++11-o main -lglfw -lglew -framework OpenGL main.cpp

请注意,稍后我们将使用一些 C++11 功能,因此我们使用 -std=c++11 进行编译。 在这两种情况下,请确保您已安装 GLFW 3。 在 Linux 上,根据您的发行版,您可以使用包管理器,例如 在 Ubuntu 上,您可以使用以下命令安装 GLFW,

sudoapt install glfw3 glew

在 Mac OS X 上,我个人更喜欢使用 Homebrew,

brewinstall glfw glew

不幸的是,我没有安装 Windows,但也许这篇文章可以帮助您在 Visual Studio 中设置 GLFW 项目。

应该这样做! 如果您成功编译了程序,您应该会看到一个标题为“Space Invaders”的红色窗口,如上图所示。

结论

您可能已经从这篇文章中意识到,在 C++ 中使用 OpenGL 上下文创建一个简单的窗口并不是一件简单的任务,即使使用像 GLFW 这样的库也是如此。 请注意,我们仍然没有绘制任何东西。 设置一些简单的绘图例程也需要在现代 OpenGL 中进行一些设置。 幸运的是,我们只需要做一次,下一个游戏将重用我将在本博客系列中介绍的大量代码。

相关推荐: