铁血丹心

 找回密码
 我要成为铁血侠客
搜索
查看: 8562|回复: 14

[通用] 关于SDL_Surface的一些心得

  [复制链接]
发表于 2013-5-7 20:22 | 显示全部楼层 |阅读模式

马上注册,结交更多侠友!

您需要 登录 才可以下载或查看,没有账号?我要成为铁血侠客

x
本帖最后由 weyl 于 2013-5-7 21:25 编辑

为了方便,Surface这里译成表面。

这里我只讨论两种表面,即32位色的RGBA和RGB两种。其他的均不讨论。

首先,两种表面的Alpha值含义一样,0是全透明,255是不透明,以此类推。
这两种表面中,每个像素均用32位(4字节)的无符号整数表示。其中当然有3个字节记录了RGB的值,顺序是与操作系统有关的。
在RGB表面中,透明数据是用ColorKey和Alpha两个值处理的。凡是某个像素的值与ColorKey相同,则视为这个像素是透明的,或者更严格的说法是被忽略的。如果Alpha的值不为255,那么整个表面上不被忽略的像素,均按照这个值进行半透明处理。
在RGBA表面中,一般来说表面自己的Alpha值是无用的,同时每个像素都有自己的Alpha值,所以有的表面每个点都可以是不同的透明度。而ColorKey仍然是标记被忽略像素的。
标准的PNG格式载入到表面上的时候,如果不作任何处理,使用的是RGBA格式。

在载入的时候,最好是用SDL_DisplayFormat或者SDL_DisplayFormatAlpha将刚刚载入文件的表面转成适合贴图的格式,这样可以大大提高速度。

对这两种格式来说,进行混合色和半透明处理,应当使用不同的方法。

1. 半透明
RGB格式的半透明,只需设好ColorKey和Alpha两个值就可以了。RGBA格式的半透明因为每个像素的值不同,如果遍历修改的话,速度会比较慢,直接转的话,可能原本透明的像素的RGB值是一些未处理的混乱数据。整体处理的方法是先提取背景的部分为一个小的RGB,将RGBA源画到此RGB目标上,再设置这个小RGB表面的ColorKey和Alpha。这里利用的是同样色值的Alpha混合结果不变。

2. 混合色
如果源图是RGB,那么只需设置源的Alpha,将其画到一个单色的RGB表面上,设置结果的ColorKey即可。如果源图是RGBA,那么首先设置一个单色的RGBA表面,填充为需混合的颜色,但是颜色值的A位设置为混合用的Alpha值,再将这个单色RGBA表面画到源图上去,将结果转为RGB,再设置透明色。

上面的方法避免了单独遍历全部像素,效率应该会高一点。应该还会有更好的方法。

评分

参与人数 1声望 +15 收起 理由
winson7891 + 15 表示大部分人路过都看不懂吧~但意思意思

查看全部评分

【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-7 22:48 | 显示全部楼层
RGBA怎么提取出背景部分

点评

第一个方法,没怎么明白  发表于 2013-5-8 13:49
什么意思  发表于 2013-5-8 13:43
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2013-5-8 15:18 | 显示全部楼层
本帖最后由 weyl 于 2013-5-8 15:19 编辑

回复 蓝烟清 的帖子
  1.               //注意, 使用以下特殊算法, 是由图片格式决定
  2.               //资源标准为带有透明通道的Surface, 因此总的Alpha和ColorKey值无效
  3.               //将所画图片直接画入背景, 再将结果与背景混合
  4.               tempscr := SDL_DisplayFormat(CurSurface);
  5.               SDL_BlitSurface(scr, @dest, tempscr, nil);
  6.               SDL_BlitSurface(CurSurface, nil, tempscr, nil);
  7.               SDL_SetAlpha(tempscr, SDL_SRCALPHA, 255 - alpha * 255 div 100);
  8.               SDL_BlitSurface(tempscr, nil, scr, @dest);
  9.               SDL_FreeSurface(tempscr);
复制代码
上面是部分代码,我说明一下。
scr是实际绘图的主屏幕。第一句实际上是为了获得一个尺寸和格式与源表面都一致,但是格式是RGB的一个临时表面,其实CreateRGB应该可以快些。

因为RGBA实际上自带透明通道的,如果再设一个透明值,效果是将这个图变得更透明。但是SDL本身并不支持这样(原文: RGBA->RGB with SDL_SRCALPHA The source is alpha-blended with the destination, using the alpha channel. SDL_SRCCOLORKEY and the per-surface alpha are ignored. 以及 Note that RGBA->RGBA blits (with SDL_SRCALPHA set) keep the alpha of the destination surface. This means that you cannot compose two arbitrary RGBA surfaces this way and get the result you would expect from "overlaying" them; the destination alpha will work as a mask.),如果转成RGB,那么透明通道的信息会丢失,甚至原来透明通道的RGB部分可能是一些错误的值。

这个方案就是将所需的主屏提取出一部分作为背景,然后将源图画到背景上。这时需要贴上去的图变成了图片+主屏的一部分,再设置这个贴图的透明值,贴到主屏上就可以得到更透明的效果了。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-8 15:22 | 显示全部楼层
回复 weyl 的帖子

不看代码,还真难明白。。。
现在懂了



【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-8 22:31 | 显示全部楼层
为什么大神们不用SDL2呢? sdl2 的速度快 而且可以加入了屏幕键盘 触屏等有用的东东
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-8 22:52 | 显示全部楼层
回复 kimonline 的帖子

重搞太麻烦了,这个东西糊弄着用。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-8 22:57 | 显示全部楼层
其实SDL2 和 SDL 1.2 的API 基本相同的 ,就是在 视频部分有区别
不需要完全重搞,只要将游戏的视频部分从SDL 1.2 移植到SDL 2
我最近比较忙,有空的时候我会研究一下,因为 SDL 1.2 按照官方所说的话
“SDL_surface 没有真正实现硬件加速的”
而SDL2 可以使用 SDL_Texture 速度灰常快
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-8 23:01 | 显示全部楼层
本帖最后由 bttt 于 2013-5-8 23:03 编辑

回复 kimonline 的帖子

pas头文件能翻译吗?
如果改用纹理,干脆直接用gl吧……

额,我看了一下,有fpc的翻译版。那么以后或许可以用。
sdl最大的好处还是跨平台吧。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-8 23:23 | 显示全部楼层
呵呵 楼上的兄弟说的有道理
SDL2 速度快 就是因为他接近底层操作
不过 官网的论坛上有人说 可以用SDL_Surface 操作,然后最后在渲染到屏幕的时候 通过转换函数 将 surface 转换 texture 进行渲染,就算是这样的话,也是比sdl 1.2 快
这个问题其实我没有试验过,也不太好说
其实我还是希望weyl 可以考虑下SDL2 ,因为SDL2 库已经成熟 这个月就要正式发表

其实我真心觉得就是金庸的操作方法 操作模式有点老化,停留在90 dos年代
如果能有什么办法修正一下,那可以让这个游戏提升一个档次,举例来说: 那个45度斜向走路其实很过时了,还有如果能点击人物就可以进行对话,那么会很爽,走路很累的,再如果能有个世界大地图,在地图上点击一下就可以到达一个地方,那也很爽
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-8 23:46 | 显示全部楼层
回复 kimonline 的帖子

你说的那些功能,和SDL1.2或者是SDL2都没有直接的关系
鼠标走路和鼠标点击对话,这个在我最新的PC版本,7.2里已经实现了。 用的是SDL1.2

SDL1.2要转成SDL2.0是非常困难的,不仅涉及到修改函数内容,还有一些实现的思路都要进行修改。

再加是SDL2的资料真的非常有限,很多问题找不到解决方案,没有实例。有些API还在更新的过程中,学习或者测试一下还可以,暂时不考虑做到游戏中。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2013-5-8 23:54 | 显示全部楼层
回复 kimonline 的帖子

目前的版本里面,最终的输出如果使用硬件加速的话,实际上就是转成了gl纹理。

如果sdl2能直接用纹理,全部运算在显存中进行,倒也可以考虑。

不过问题是:这么个古老的2D游戏,现在硬件的发展又很快,其实用纹理的效率提升可能并不太明显了。就SDL本身来说,特点就是易于使用,可惜SDL_Mixer又废柴到现在。如果哪个大大做一个新思路的游戏,如果要用sdl,当然应该优先考虑2的。


PS:当年俺不会用C,用pascal写了这么个东西,现在这类程式不好找,好多东西都我一个人搞,很累啊……
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-9 12:09 | 显示全部楼层
SDL 确实可以用直接用纹理操作,抛开他这个surface 不用,其实提高效率的初衷是跨平台,特别是手机平台
weyl 大的pascal 我不会,不知道有没有人将这个转成C
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2013-6-15 18:32 | 显示全部楼层
本帖最后由 weyl 于 2013-6-15 19:08 编辑

关于sdl_ttf生成的表面

经过我实验得到, ttf渲染得到的表面为一个RGBA的表面, 同时, 表面上的所有像素的RGB值均为你指定的那个值, 而只是A值在每个点不同.

如果在blit时需要将透明通道值一起复制过去, 需要用以下函数处理

SDL_SetAlpha(surface, 0, 255);

而SDL_SetAlpha函数flag为0时的说明, 好像网上现在找到的都不是很具体. 暂且认为可以这样用吧.


这个函数的用法涉及一个文字输出的处理, 即文字分层显示. 简单地说, 如果指定窗口的图像可以被拉伸, 那么原本的图片还可以, 文字就会变得模糊. 如果想要放大之后的文字仍然显得锐利, 就需要将文字画到一个与窗口大小相同的表面上, 每当需要画文字时都重新计算文字的位置, 最后将画面拉伸后与文字表面合并.
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2017-9-17 00:49 | 显示全部楼层
基于SDL1.2的游戏,如果需要转至SDL2,假如画图时并没有使用基于纹理的方案,那么表面的用法一定要注意下面几个问题:

基本表面应该使用ARGB格式,注意4个值的MASK一定要设置正确,这个也是一般的默认格式。在生成一个新的表面的时候,也应该将其转为ARGB格式,调用SDL_ConvertSurfaceFormat的时候,第二个参数应直接取主表面的值。

尽量不使用ColorKey,而用透明通道代替,否则绘图的时候可能会产生一些奇怪的错误。也就是说,要保持参与绘图的表面都是同一格式,才能保证按照你所需的效果绘图。类似将RGB的表面画到ARGB的表面的操作要尽量避免。

SDL1.2的表面并不支持上面所说的透明度上叠加透明度,但是SDL2的表面支持,当然速度远不及使用纹理。

SDL_DisplayFormat和SDL_DisplayFormatAlpha全部使用SDL_ConvertSurfaceFormat代替。

SDL_SetColorKey的第二个参数必须为SDL_TRUE,并且这个操作应该避免,使用设置A通道来代替。

SDL_SetAlpha使用SDL_SetSurfaceAlphaMod代替,但是在源和目标格式不一致的时候,结果可能不正确。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2017-9-17 00:56 | 显示全部楼层
键值响应现在使用系统的,必要的时候要读取按键状态。
键值在各个平台的值全部统一。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。

本版积分规则

小黑屋|手机版|铁血丹心

GMT+8, 2024-5-2 06:17

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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