铁血丹心

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

[通用] 让引擎支持画面放大

[复制链接]
发表于 2013-1-1 14:16 | 显示全部楼层 |阅读模式
本帖最后由 weyl 于 2013-1-2 23:44 编辑

经常有人抱怨说画面太小,也经常有人回答说全屏就可以了。不过应该还是有的人不喜欢全屏吧。
这里是让引擎支持画面放大的方法。

首先我们要引入SDL_gfx这个库,利用它来实现画面缩放。
然后,我们需要自定一个标准分辨率,因为界面设计都是以标准分辨率为基础的。以pascal原版为例,用的是640*440。
当我们画图时,把图都画在一个内部的sdl_surface上面。为了尽量少修改本来的代码,我们加一个指向真实画面的surface指针scr,令其指向实际的画面。
  1. Scr := SDL_SetVideoMode(640 * 2, 440 * 2, 32, SDL_SWSURFACE or SDL_DOUBLEBUF or SDL_RESIZABLE);

  2.   screen := SDL_CreateRGBSurface(SDL_SWSURFACE or SDL_DOUBLEBUF, 640, 440, 32,0, 0, 0, 0);
  3.   
复制代码
注意初始化视频时多加了一个SDL_RESIZABLE,令窗口大小可以调节。
这样,之前对screen的操作都改在内部进行了。在需要把画面显示出来的时候,我们这次在sdl_updaterect上面做文章,因为显示画面用的都是这个。

增加一个子程:
  1. procedure SDL_UpdateRect2(scr1:PSDL_Surface; x, y, w, h: integer);
  2. var
  3.   xx, yy, ww, hh: integer;
  4.   tempscr:Psdl_surface;
  5. begin
  6.   xx:= x*scr.w div scr1.w;
  7.   ww := (x+w+1)*scr.w div scr1.w-xx;
  8.   yy:=y*scr.h div scr1.h;
  9.   hh:= (y+h+1)*scr.h div scr1.h -yy;
  10.   if ww+xx>scr.w then ww:=scr.w-xx;
  11.   if hh+yy>scr.h then hh:=scr.h-yy;

  12.   tempscr := sdl_gfx.rotozoomSurfaceXY(screen, 0, 1.0*scr.w/scr1.w, 1.0*scr.h/scr1.h, 1);
  13.   SDL_BlitSurface(tempscr, nil, scr, @dest0);

  14.   SDL_UpdateRect(scr, xx, yy, ww, hh);
  15.   sdl_freesurface(tempscr);
  16. end;
复制代码
这里变量命名比较随意,建议实用时用正规点的。
我们可以看到,这时是利用了一个gfx的缩放sdl_gfx.rotozoomSurfaceXY对screen进行处理,保存到临时的一个surface上面,然后将这个临时的surface显示在真实画面上。这个缩放函数的最后一个参数是平滑,如果不使用,那么速度几乎没什么变化,但是会有明显的像素感,字体可能会感觉很破碎;使用的话,画面质量会好很多,但是在分辨率较高时会明显拖慢游戏速度,。
dest0是一个全局的TSDL_Rect,里面的值都是0。然后,查找SDL_UpdateRect,全部换成SDL_UpdateRect2(利用一些编辑器的批量替换功能),注意不要把这个新的也一起换了。


如果让窗口可以随时变化,还需要在sdl的事件查询中对窗口变化进行响应,需要在所有涉及sdl事件的部分增加类似下面这样的代码:
  1. SDL_VIDEORESIZE:
  2.         begin
  3.           ResizeWindow(event.resize.w, event.resize.h);
  4.         end;
复制代码
其中:
  1. procedure ResizeWindow(w,h: integer);

  2. begin
  3.   scr := SDL_SetVideoMode(w, h, 32, SDL_SWSURFACE or SDL_DOUBLEBUF or SDL_RESIZABLE);
  4.   ZoomX := 1.0*scr.w/screen.w;
  5.   ZoomY := 1.0*scr.h/screen.h;
  6. end;   
复制代码
ZoomX和ZoomY当然是两个浮点的全局变量了。这两个变量是为了让鼠标在新的分辨率下面响应正常。
然后,将涉及鼠标坐标的全部位置,均用这两个变量处理,例如event.botton.y 全部替换成round(event.botton.y / ZoomY),x也一样处理。还有有些地方可能用到了SDL_GetMouseState这个函数,也需要注意。

下面就是一个画面示范了,是我随便拖动窗口弄出的一个分辨率:

本帖子中包含更多资源

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

x

评分

参与人数 1声望 +15 收起 理由
winson7891 + 15 强大的引擎升级

查看全部评分

【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2013-1-1 21:26 | 显示全部楼层
本帖最后由 weyl 于 2013-1-3 16:01 编辑

注意用gfx的平滑缩放效率比较差,配置一般的电脑可能会很卡,彻底解决要用opengl。
在介绍OpenGL之前,首先说一个gfx的替代方案SPriG,这是一个基于SDL的扩展库,基本上覆盖了gfx的全部功能,而且使用了快得多的算法。当然在增加了效率的同时也有一些缺点,有时计算出的结果会不太完美。不过在游戏里面,因为刷新率很高,不完美的地方只要不引人注意就可以了。
这个库目前只有C语言版,如果你的编程语言是C就可以直接用头文件。当然作为同一量级的pascal语言也可以使用,方法是直接调用dll中的函数。这里我们需要用到的是Tranform这个功能。
将以下代码写在文件的开头,dll文件置于游戏目录下面,这样就可以用SPG_Transform这个函数了。

  1. function SPG_Transform(src: PSDL_Surface; bgColor: Uint32; angle: single; xscale: single; yscale: single; flags: Uint8): PSDL_Surface; cdecl; external 'sprig.dll';
复制代码

把上面使用gfx的语句改为:
  1. tempscr := SPG_Transform(screen, 0, 0, ZoomX, ZoomY, 1);
复制代码
编译看效果。

这个函数比gfx要快很多,在i等级的cpu上已经几乎没有延迟了。但是需要指出的是,SPriG这个库仍然是软件方案,只是使用了速度较快的算法,毕竟我们不能指望每个玩家都有一台i级别的电脑。真正彻底解决的方案还是需要利用显卡。

下面将介绍如何使用OpenGL进行硬件加速,为了简单起见,我们仅在实际绘图时采用硬件加速,即在最终显示的时候,将已经绘制好的SDL的Surface转成OpenGL。当然,在初始化窗口的时候,需要用SDL_OPENGL这个项。

需要在uses部分添加gl和glext,并定义一个GLuint量TextureID,以下代码将SDL的表面转成OpenGL的纹理。

  1.     glGenTextures(1, @TextureID);
  2.     glBindTexture(GL_TEXTURE_2D, TextureID);
  3.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screen.w, screen.h, 0, GL_BGRA, GL_UNSIGNED_BYTE, screen.pixels);
复制代码

设置拉伸时使用的方式,最后一个是线性插入,可以理解为平滑效果,也可以设置为GL_NEAREST方式,即非平滑效果。
  1.       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  2.       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
复制代码

显示的时候使用下面的代码:
注意,Begin和End之间的语句是定义矩形纹理四个角在窗口上的位置,实际上你完全可以把它们定义到别处,做出3D拉伸的效果。最后一句是将屏幕更新。
  1.     glENABLE(GL_TEXTURE_2D);
  2.     glBEGIN(GL_QUADS);
  3.     glTexCoord2f(0.0, 0.0);
  4.     glVertex3f(-1.0, 1.0, 0.0);
  5.     glTexCoord2f(1.0, 0.0);
  6.     glVertex3f(1.0, 1.0, 0.0);
  7.     glTexCoord2f(1.0, 1.0);
  8.     glVertex3f(1.0, -1.0, 0.0);
  9.     glTexCoord2f(0.0, 1.0);
  10.     glVertex3f(-1.0, -1.0, 0.0);
  11.     glEND;
  12.     glDISABLE(GL_TEXTURE_2D);
  13.     SDL_GL_SwapBuffers;
复制代码





【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-1-2 15:12 | 显示全部楼层
好强大,估计缩放会慢点吧,不过真是越来越完善了~偶像,能给我签个名吗?
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-1-3 07:31 | 显示全部楼层
总觉得这么搞不是正路……

不过还是支持引擎的升级。

有开关不?是不是强制性要这样改的?

点评

开关……自己做  发表于 2013-1-3 18:19
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-1-3 09:31 | 显示全部楼层
俺只求ini文件里能看见分辨率设定就知足了~~

点评

猪3应该马上就能有  发表于 2013-1-3 12:45
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-3-7 15:57 | 显示全部楼层
C代码

  1. void SDLCALL SDL_UpdateRect2(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  2. {
  3.   SDL_Surface *tempscr;
  4.   tempscr = rotozoomSurfaceXY(screen, 0, 1.0*scr->w / screen->w, 1.0*scr->h/screen->h, 1);
  5.   SDL_BlitSurface(tempscr, NULL, scr, NULL);
  6.   
  7.   SDL_UpdateRect(scr, 0, 0, 0, 0);
  8.   SDL_FreeSurface(tempscr);
  9. }

复制代码

点评

K大,还是有些无从下手。。  发表于 2013-4-1 10:15
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-3-27 08:19 | 显示全部楼层
学习下            
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-20 09:28 | 显示全部楼层
最近浅浅研究了这套代码在Lua上的可行性发现,其实可以将画面在分层即只放大缩小最下面的画面部分,对上面的字体采用自适应调整大小,这样似乎就可以避免字体经过放大缩小后丑陋不堪的情况。
目前主流Lua版本中使用的是扩大每一个图片的大小,随后更换间距绘制达到放大的目的,理论来说也是可以的,只不过弱点很明显即不能smooth。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。

本版积分规则

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

GMT+8, 2024-5-3 20:05

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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