C++/SDL游戏开发(一)

PS:本篇主要参考Sanjav Madhav的《Game Programming in C++》和相关SDL文章作者。

关于我:学软件的苦逼大学生,在大一的暑假用C++写了个pvz精简版,其视频已上传至b站:

【植物大战僵尸,但是大二生的C++项目】 https://www.bilibili.com/video/BV1Eg41187pL/?share_source=copy_web&vd_source=14a9dd4c3de61f01a163154ba761fce0

本来答应了今年暑假放教学视频的,但由于大大小小的事情就耽误了(其实就是不会做视频),也由于自己想多学习一下C++/C#,因此准备在CSDN分享一些关于C++游戏编程的知识。虽然真正开发游戏的时候都会使用自研/商业引擎来实现高效开发,但我觉得从底层开始像搭积木一样用手把代码搭起来也是很有乐趣的,并且能提高对游戏运行原理的理解。

 由于个人还是个纯小白,还没有老油条级别的能力,所以本教程(攻略)主要面向在校学生,特别是对游戏感兴趣的高中生或本科生。本帖最适合的人群可能是,在学校里学习了或自学了一种编程语言,但却最终止步于一个冰冷冷的小黑窗,于是想要更进一步,只用代码实现出一个有图形界面的游戏。

 那么话不多说,我们开始。

一、前期准备工作——导入外部库

在基本的编程语言课程中可能很少会遇到多文件的情况,也很少会调用外部库,因此以防万一,这里还是介绍一下管理多文件以及链接外部库的方法。

1.首先我们在VS中新建了一个空项目之后,找到项目属性,C/C++ → 常规 → 附加包含目录,在这里加上SDL文件们的根目录。

2.链接器 → 常规 → 附加库目录,在这里面写上lib文件的路径。与之前同理,我的lib文件都在lib文件夹中。

3.链接器→输入→附加依赖项,在里面写上SDL2.lib和SDL2main.lib。

4.调试 → 环境,在里面写上PATH=(dll文件的路径)。也可以直接把dll文件放在项目文件目录下,就不需要在这里添加新路径了。

至此所需的配置全部装备完毕,可以试着include一下SDL.h看看有没有配置成功。

二、游戏编程思路

在以往面对小黑窗的编程中,写的大多数程序都是当按下运行键的那一瞬间,程序基本就执行完毕了,直接把期望的输出展示在小黑窗上。偶尔也会有需要一次性输入的程序,不过当输入完毕后程序一般也会眨眼间执行完毕。

然而游戏需要玩家与程序进行不断的互动,因此需要让程序进入一个循环中,防止它自行结束,只有当玩家选择退出游戏的时候它才能停止工作。但如果直接就写个死循环上去,对计算机的负担就太大了。在游戏程序中,每一次循环就是1,大家常说的60帧就是指每秒中程序进行了60次主循环。

其实往简单了说,游戏编程最基本的主循环就是:

1. 处理事件(主要是玩家的输入)

2. 更新游戏中各个事物的状态

3. 输出(包括画面、音乐等)

如果有Unity经验的人可能会很熟悉Update(),为了完成游戏逻辑,在Unity里一般就会把第1步和第2步的代码写入Update()或FixedUpdate()等函数之中,然后每一帧都会自动调用所有物体的Update()来实现状态更新。在使用这些引擎的时候一般来说就不用考虑第3步了,不过如果自己从底层开始写的话还是无法避开这步的。

没有引擎经验的人也可以联想一些熟悉的游戏。比如马里奥,如果放着不动,就永远停留在一个画面上。当玩家输入前进键的时候,会先计算出马里奥在这一帧的新位置,然后渲染器会绘制背景、砖块等,再根据第2步得到的马里奥新位置,把它绘制到屏幕上对应的位置中。

那么现在,我们试着把最基本的框架搭起来。

先看一看Game类的构造:

class Game
{
public:
	//构造函数
	Game();

	//初始化
	bool	Initialize();
	//主循环
	void	Loop();
	//游戏结束
	void	Shutdown();

private:
	//处理事件
	void	Event();
	//更新各种状态
	void	Update();
	//渲染
	void	Draw();

	bool	mIsRunning;		//运行状态
};

我们用mIsRunning来表示整个游戏的运行状态,初始化为true。当mIsRunning为true的时候,就可以执行主循环了,因此Loop()函数可以写成这样:

void Game::Loop()
{
	while (mIsRunning)
	{
		Event();
		Update();
		Draw();
	}
}

如此,最最基本的骨架就完成了,当然因为main函数里什么都没写,所以目前甚至都没法运行,不过本章主要是理解一下原理,下一章将正式从用SDL新建窗口开始。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
#include #include //用键盘控制精灵移动 int main(int argc, char ** argv) { SDL_Surface * screen; //主表面 SDL_Surface * image; //用来放MM-----的图片信息(像素) SDL_Surface * PlayerImage; //用来测试的图片 SDL_Event event; Uint32 BeginTicks, EndTicks; SDL_Rect PRect, BRect; //PRect对应精灵的移动的小图位置(实现动画),BRect对应精灵在屏幕的位置。 unsigned char PlayerStarts = 0; unsigned char PlayerIndex = 0; bool bAppRun = true; //初始化SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) { fprintf(stderr, "SDL_Init %s\n", SDL_GetError()); return -1; } //初始化成功设置退出要调用的函数SDL_Quit atexit(SDL_Quit); //创建一个640X480 16-bit 模式的主表面 16位可以让MM的效果好看一点 screen = SDL_SetVideoMode(230, 230, 16, SDL_SWSURFACE); if (screen == NULL) { fprintf(stderr, "Couldn't set 640x480x8 video mode %s\n", SDL_GetError()); return -1; } //读取MM图片信息,并创建一个表面,并把数据填入该表面中。 image = SDL_LoadBMP("./mm.bmp"); //请在终端里运行该程序 if (image == NULL) { fprintf(stderr, "Couldn't load MM, %s\n", SDL_GetError()); //遗憾你不能显示MM了,不过你可以用图片浏览程序看。 return -1; } //读取player.bmp PlayerImage = SDL_LoadBMP("./player.bmp"); //请在终端里运行该程序 if (image == NULL) { fprintf(stderr, "Couldn't load MM, %s\n", SDL_GetError()); //遗憾你不能显示MM了,不过你可以用图片浏览程序看。 return -1; } //读取第一个像素 Uint8 key = *((Uint8 *)PlayerImage->pixels); //设置色键 SDL_SetColorKey(PlayerImage, SDL_SRCCOLORKEY, key); //有了MM的表面了,就可以显示了。 //将MM的表面画在我们的主表面上,用MM来作为背景 if (SDL_BlitSurface(image, NULL, screen, NULL) < 0) { //解释一下NULL,第一个是按照image的尺寸显示,第二个是默认显示。你也可以指定大小,不过要用到SDL_Rect你可以看一看帮助。 fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError()); //看看提示吧 return -1; } PRect.x = 0; //初始化动画显示的图片。 PRect.y = 0; PRect.w = 32; PRect.h = 48; BRect.x = 0; //初始化精灵的位置。 BRect.y = 0; BRect.w = 32; BRect.h = 48; //贴上测试用的表面 if (SDL_BlitSurface(PlayerImage, &PRect, screen, &BRect) w, image->h); BeginT

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Deryck_德瑞克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值