SDL入门教程(十一):1、SurfaceClass类的再设计

[复制链接]

该用户从未签到

2380

主题

2433

帖子

9139

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9139
QQ
跳转到指定楼层
楼主
发表于 2017-12-19 09:53:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

想要查看内容赶紧注册登陆吧!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
1.1:为了按钮做准备

        按钮是鼠标事件响应的象征,在PC游戏中起着十分重要的作用。这一章节,我们开始通过SDL提供的底层函数,自己来设计按钮。
        按钮一般有这么几种状态:
out: 鼠标不在按钮上;
over: 鼠标在按钮上;
down: 鼠标按下了;
up: 鼠标松开了;
        其中,down和up又可以细分为鼠标是在按钮上按下松开的,还是在按钮外按下松开的。
        我们先从按钮的表现形式——图片来分析这些问题。
        为了表现不同的状态,我们需要多张图片。至少的,out与over和down中的至少一张图片应该是不一样的,这样才能给人以“按下了”的视觉效果。也就是说,如果我们构建按钮类,这个类将会包含我们之前设计的SurfaceClass类。这样,根据我们之前讨论的一些C++细节问题,我们必须重新小心的设计SurfaceClass类。

1.2:为SurfaceClass设计基类

        我们之前使用DisplaySurface本身作为TextSurface的基类,这是因为我们希望通过基类本身引用派生类,从而不需要为基类和派生类分别写函数。同样的,我们希望在ButtonClass中直接使用基类作为成员数据,这样,ButtonClass可以不需要为派生类重新构建。在之前的DisplaySurface中,我们可以看到,大部分方法,比如最为重要的blit()方法,所涉及到的成员数据仅仅就是SDL_Surface* pSurface,这一点,TextSurface类也是一样的。DisplaySurface类通过图片创建pSurface,TextSurface类通过字库创建pSurface,他们的创建条件不尽相同,TextSurface需要打开TTF_Init(),还需要打开字库TTF_OpenFont(),所以,他们的构造函数与析构函数是不一样的。一种更加清晰的关系,是建立起他们的基类,然后把他们的区别点分开处理,而不是之前采用的if来判断处理。
        最清晰的办法,是把BaseSurface设计成为抽象基类(ABC),但是ABC的问题在于,无法创建ABC本身的对象,也就是说,我们需要在ButtonClass中包含的BaseSurface对象无法建立,所以,我们不能把BaseSurface设计成为ABC。我想到的办法,是将BaseSurface的默认构造函数仅仅提供给派生类使用,也就是说,因为BaseClass的默认构造函数本身是不能建立起必要的数据的,比如pSurface和pScreen,我们暂时都用空指针代替。这里的思想其实还是ABC的,让基类仅仅提供算法,即使算法所需要的元素还尚不存在。但是,只要这些元素存在了,BaseSurface也就可以完成这些算法,所以,我们把BaseSurface的复制构造函数设计为公共的,这很重要,这样才为我们通过派生类去初始化基类的构造函数初始化列表提供了可能。
        我们把基类命名为BaseSurface,之前的DisplaySurface我们用更形象的名称代替,叫PictureSurface,然后TextSurface不改名。

1.3:如何深度复制SDL_Surface ?

        因为PictureSurface和TextSurface的构造函数都涉及到了堆操作,也就是说,SDL_Surface是建立在堆上的。我们需要通过基类的复制构造函数复制SDL_Surface,必须找到合适的工具。具体来说,新对象的pSurface必须指像一个新建立起来的SDL_Surface对象,而非被复制的对象本身。
        我最先想到的是用new...delete组合,但是失败了。为什么呢?我们研究SDL_Surafce结构本身,发现在之中包含着一些其它的指针。比如SDL_PixelFormat *format和void *pixels。也就是说,SDL_Surface本身的构建也有堆操作,而且,因为SDL_Surafce是C风格的结构而不是类,它不能提供深度复制的操作,所以,即使我们用new为SDL_Surface申请了新空间,SDL_Surface本身也不会为format和pixels申请新的副本。当被释放掉原本的时候,副本将寻找不到原本的format和pixels,从而产生错误。
        我们另外能找到的可以深度复制SDL_Surface的函数,是:
SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface);
SDL_Surface *SDL_ConvertSurface(SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags);
        这两个函数貌似都是可行的。实际上,基本上也都是可行的。但是涉及到文字的时候,SDL_DisplayFormat将不能正确的转换Blended和Shaded的文字,所以,最后只能使用SDL_ConvertSurafce()。
新构建的SurfaceClass源代码见:
http://www.cppblog.com/lf426/archive/2008/04/14/47038.html
分享到:  QQ好友和群QQ好友和群
收藏收藏
回复

使用道具 举报

快速回复高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表