上一篇:Xcode与C++之游戏开发:2D图形
接下来在前两天游戏骨架的基础上实现一个经典的乒乓球(Pong)游戏。游戏是这样的,一个球在屏幕上移动,玩家控制球拍来击打球。可以说乒乓球游戏是游戏开发者的 “Hello World” 项目。
绘制游戏中的物体
乒乓球球拍我们使用矩形来表示。绘制填充矩形,SDL 有 SDL_RenderFillRect
函数,它接受一个 SDL_Rect
代表的填充矩形,而矩形颜色由当前的绘图颜色决定。换句说,现在我们不改变绘图颜色,它默认就会使用那个幸福浪漫的蒂芙尼蓝。当然,颜色一摸一样,我们是看不见的。为了看得出矩形,将它修改成蓝色。
在 Game::GenerateOutput()
交换缓冲区之前写入:
// 设置绘制颜色
SDL_SetRenderDrawColor(mRenderer, 0, 0, 255, 255);
要绘制矩形,需要指定一个 SDL_Rect
结构体。这个结构体有4个参数,左上角的点x/y坐标,还有矩形的高和宽度。在绝大多数的图形库中,包括 SDL,窗口左上角的点的坐标是(0, 0),x正半轴是向右,y正半轴是向下的(和数学上的相反)。
假设我们要在屏幕上方绘制矩形作为游戏的墙,可以使用下面的 SDL_Rect
的定义:
// 顶部墙的参数
SDL_Rect wall {
0, // 左上 x 坐标
0, // 左上 y 坐标
1024, // 宽度
kThickness // 高度
};
宽度被硬编码成1024,一般来说这需要根据窗口尺寸自动修正,后面会考虑修正这个问题。kThickness
是一个 const int
常量,被设置成15,这是为了方便调整墙的厚度。
C++ 不推荐使用
#define
宏预定义,更推荐使用const
在头文件声明之后加入:
const int kThickness = 15;
最后,用 SDL_RenderFillRect
绘制矩形,传入 SDL_Rect
指针:
SDL_RenderFillRect(mRenderer, &wall);
这样游戏窗口上面多了一道墙,类似的,可以画出底部的墙和右边的墙,只需要通过改变 SDL_Rect
的参数。比如,下面那道墙左上角的 y 坐标就是 768 - kThickness
(因为窗口初始化时高度被初始化为768)。
// 绘制底部墙
wall.y = 768 - kThickness;
SDL_RenderFillRect(mRenderer, &wall);
// 绘制右边的墙
wall = {
1024 - kThickness,
0,
kThickness,
1024
};
SDL_RenderFillRect(mRenderer, &wall);
左边的墙呢?留着给玩家打乒乓球。
墙硬编码可能问题不大,乒乓球球和球拍就不能硬编码了。随着游戏循环,球拍是要会动的。实际游戏编程中,球和球拍应该抽象成类,但是现在我们姑且先用变量代替一下硬编码。
首先,先定义一个 Vector2
结构体来存储 x 和 y 坐标。这个定义放到 Game.hpp
之中:
// Vector2 结构体仅存储 x 和 y 坐标
struct Vector2
{
float x;
float y;
};
接着添加两个 Vector2
的成员变量到 Game
类中,一个作为球拍 mPaddlePos
,一个作为球 mBallPos
。
// 球拍位置
Vector2 mPaddlePos;
// 球的位置
Vector2 mBallPos;
之后在初始化时 Game::Initialize()
赋予一个合理的初始值。
// 初始化球拍和球的坐标
mPaddlePos.x = 10.0f;