文章目录
Prerequisite
最近在学c++,直接看书学习基础语法有点无聊,于是希望结合游戏开发来深入了解这门语言。网上搜罗了一番,决定从四子棋(connect four)着手,大概300来行代码。这个系列目前只实现了“人人对战模式”,“人机博弈”的算法有空再完善它。首先说一下编程环境:
- 编程语言:c++
- 游戏开发库:SDL-2.0
- 开发环境:windows或者linux,Visual Studio或者其他IDE
完整代码已经放上github了,在这里
这里跳过SDL-2.0的环境配置了,基本就是跟c++使用第三方库是一样的,准备好必要的头文件以及库文件,让编译器知道去哪儿找它们就可以了。开始吧!
这一部分我们只是简单地显示一个指定大小的窗口5秒钟,然后退出程序
显示窗口
首先,SDL2.0要求我们做一些初始化的工作。另外,因为我们后面会使用到png图片和字体的加载,我们这里一并把这些初始化工作都作了,先写个initialize()
函数:
// main.cpp
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
using namespace std;
bool initialize() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Failed to initialize SDL! SDL Error: %s\n", SDL_GetError());
return false;
}
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags)){
printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
return false;
}
if (TTF_Init() == -1) {
return false;
}
return true;
}
我们先把会用到的三个头文件包含进来:
SDL.h
:提供的基本的功用,如窗口程序SDL_image.h
:提供图片加载的函数SDL_ttf.h
:提供字体的加载,这个在后面会用到
分别初始化这三个模块,如果有错误则将相应错误打印出来,并且返回false
;否则返回true
。
如果初始化成功,我们就可以着手我们的窗口程序了。因为后面要添加许许多多的功能,我们把整个游戏逻辑都封装在一个类里:
// connect_four_0.h
#ifndef CONNECT_FOUR_0_H
#define CONNECT_FOUR_0_H
#include <SDL.h>
#include <SDL_ttf.h>
#include <SDL_image.h>
#include <cstdio>
using namespace std;
SDL_Window *gWindow = nullptr;
constexpr int GRID_SIZE = 50;
class ConnectFour {
public:
ConnectFour() = default;
ConnectFour(int nbWGrids, int nbHGrids) :
_nbWGrids(nbWGrids),
_nbHGrids(nbHGrids),
_nbGrids(nbWGrids * nbHGrids)
{
_winHeight = GRID_SIZE * nbHGrids;
_winWidth = GRID_SIZE * nbWGrids;
}
void start() {
pre_run();
run();
}
private:
int _nbHGrids = 0; // 竖直方向的格子数
int _nbWGrids = 0; // 水平方向的格子数
int _nbGrids = 0; // 总的格子数,就是上面两个变量的乘积
int _winHeight = 0; // 窗口的高度
int _winWidth = 0; // 窗口的宽度
void pre_run() {
gWindow = SDL_CreateWindow("Connect Four", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, _winWidth, _winHeight, SDL_WINDOW_SHOWN);
}
void run() {
SDL_Delay(5000);
}
};
#endif
首先我们定义一个全局变量gWindow
,这个指针指向我们的窗口程序。另外,我们定义一个常量GRID_SIZE
,指明每个四子棋格子所占的像素个数,这里我们设定为50,那么后面我们计算窗口的大小就是:每个格子所占像素个数 x 格子个数。
在ConnectFour
类里有4个私有变量,它们的含义分别如上面的注释所示。注意,所有的类成员变量我都以下划线_
开始了,这只是我自己的编程风格,不一定要采纳。该类里面定义了一个有参数的构造函数ConnectFour(int nbWGrids, int nbHGrids)
,允许用户指定格子的数目,然后也可以计算出相应的窗口宽度和高度。
ConnectFour
类主要提供了一个start()
接口来启动这个窗口。我们现在就只是创建一个窗口,然后等待5秒便退出:
gWindow = SDL_CreateWindow("Connect Four", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, _winWidth, _winHeight, SDL_WINDOW_SHOWN);
创建窗口函数的参数分别为:窗口名字(title)、窗口的位置x和y(这里我们不指定位置)、窗口的宽度和高度、是否显示窗口。
有了这个我们就可以回去main函数:
// main.cpp
#include "connect_four_0.h"
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
using namespace std;
bool initialize(); // 前面定义了,这里不重复了
int main(int, char *[]) {
if (initialize()) {
ConnectFour cf(10, 8);
cf.start();
}
return 0;
}
注意这个main函数感觉怪怪的,但SDL2.0好像一定要求要这种形式的,这里因为我们不需要用到这些参数,所以我把名字省略掉了。在后续过程中,这个main.cpp
文件都不再需要改变了(#include “connect_four_0.h"可能还是要改成相应的文件)。