铁血丹心

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

[其他] 关于Pascal复刻的乱七八糟的东西

[复制链接]
发表于 2010-4-15 11:05 | 显示全部楼层 |阅读模式

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

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

x
实在乱七八糟,不知道怎么说起。就先来讨论一下怎么实现图片(非RLE8格式)的半透明显示,REL8格式半透明乌鸦大大曾经写过,就不说了~~



在SDL中可以对surface设置透明度,用到的函数是function SDL_SetAlpha(surface: PSDL_Surface; flag: UInt32; alpha: UInt8): Integer; 用法不算难,只要看看实例中怎么用就应该能明白了。




下面的代码是显示一个半透明的png,jpeg等图片的代码:
  1. procedure display_img(file_name: PChar; x, y: integer; Alpha: Uint8); overload;
  2. var
  3.   image: PSDL_Surface;
  4.   dest: TSDL_Rect;
  5.   pix1,pix2,pix3,pix4,pix5,pix6,A,Amask, color1, color2, color3: Cardinal;
  6.   i1, i2: integer;
  7. begin
  8.   if fileexists(file_name) then
  9.   begin
  10.     image := IMG_Load(file_name);
  11.     if (image = nil) then
  12.     begin
  13.       MessageBox(0, PChar(Format('Couldn''t load %s : %s',
  14.         [file_name, SDL_GetError])), 'Error', MB_OK or MB_ICONHAND);
  15.       exit;
  16.     end;
  17.     dest.x := x;
  18.     dest.y := y;
  19.     Amask := image.format.AMask;
  20.     if AMask = 0 then
  21.     begin
  22.       SDL_SetAlpha(image, SDL_SRCALPHA, alpha); //alpha是透明度,范围是0到255
  23.       if (SDL_BlitSurface(image, nil, screen, @dest) < 0) then
  24.         MessageBox(0, PChar(Format('BlitSurface error : %s', [SDL_GetError])), 'Error', MB_OK or MB_ICONHAND);
  25.       //SDL_UpdateRect(screen, 0, 0, image.w, image.h);
  26.     end
  27.     else
  28.     begin

  29.       for i1 := 0 to image.h - 1 do
  30.         for i2 := 0 to image.w - 1 do
  31.         begin
  32.           color1 := getpixel(image, i2, i1);
  33.           A := (color1 shr image.format.Ashift) and $FF;
  34.           if A <> 0 then
  35.           begin
  36.             testA := A;
  37.             A := A * alpha div 255;
  38.             pix1 := color1 shr image.format.Rshift and $FF;
  39.             pix2 := color1 shr image.format.Gshift and $FF;
  40.             pix3 := color1 shr image.format.Bshift and $FF;
  41.             color2 := getpixel(screen, x + i2, y + i1);
  42.             pix4 := color2 shr screen.format.Rshift and $FF;
  43.             pix5 := color2 shr screen.format.Gshift and $FF;
  44.             pix6 := color2 shr screen.format.Bshift and $FF;
  45.             pix1 := (A * pix1 + (255 - A) * pix4) div 255;
  46.             pix2 := (A * pix2 + (255 - A) * pix5) div 255;
  47.             pix3 := (A * pix3 + (255 - A) * pix6) div 255;
  48.             color3 := pix1 shl screen.format.Rshift + pix2 shl screen.format.Gshift + pix3 shl screen.format.Bshift;
  49.             putpixel(screen, i2 + x, i1 + y, color3);
  50.           end;
  51.         end;
  52.     end;
  53.     SDL_FreeSurface(image);
  54.   end;
  55. end;
复制代码
bmp图片半透明的显示也是相同道理,在这里就不写了。

图片说完了,下面说说半透明显示文字吧,文字和图片的处理不太一样,主要是因为通过TTF_RenderUNICODE_blended得到的surface无法设置透明度。那么我们就用最基础的方法,对每个像素进行操作。下面改写一下原来的DrawText函数。
  1. procedure DrawText(sur: PSDL_Surface; word: PUint16; x_pos, y_pos: integer; color: Uint32; alpha: Uint8); overload;
  2. var
  3.   dest: TSDL_Rect;
  4.   i1, i2, alpha: integer;
  5.   pword: array[0..2] of Uint16;
  6.   nullcolor, color1, color2, color3, pix1, pix2, pix3, pix4, pix5, pix6, pix7, pix8: Uint32;
  7. begin

  8.   pword[0] := 32;
  9.   pword[2] := 0;

  10.   dest.x := x_pos;

  11.   while word^ > 0 do
  12.   begin
  13.     pword[1] := word^;
  14.     inc(word);
  15.     if pword[1] > 128 then
  16.     begin
  17.       text := TTF_RenderUNICODE_blended(font, @pword[0], TSDL_Color(Color));
  18.       dest.x := x_pos - 10;
  19.       dest.y := y_pos;
  20.       nullcolor := getpixel(text, 0, 0);
  21.       for i1 := 0 to text.h - 1 do
  22.         for i2 := 0 to text.w - 1 do
  23.         begin
  24.           color1 := getpixel(text, i2, i1);
  25.           color2 := getpixel(sur, dest.x + i2, dest.y + i1);
  26.           if color1 <> nullcolor then
  27.           begin
  28.             pix1 := color1 and $FF;
  29.             pix5 := color2 and $FF;
  30.             pix2 := color1 shr 8 and $FF;
  31.             pix6 := color2 shr 8 and $FF;
  32.             pix3 := color1 shr 16 and $FF;
  33.             pix7 := color2 shr 16 and $FF;
  34.             pix4 := color1 shr 24 and $FF;
  35.             pix8 := color2 shr 24 and $FF;
  36.             pix1 := (alpha * pix1 + (255 - alpha) * pix5) div 255;
  37.             pix2 := (alpha * pix2 + (255 - alpha) * pix6) div 255;
  38.             pix3 := (alpha * pix3 + (255 - alpha) * pix7) div 255;
  39.             pix4 := (alpha * pix4 + (255 - alpha) * pix8) div 255;
  40.             color3 := pix1 + pix2 shl 8 + pix3 shl 16 + pix4 shl 24;
  41.           end
  42.           else
  43.             color3 := color2;
  44.           putpixel(sur, dest.x + i2, dest.y + i1, color3);
  45.         end;
  46.       x_pos := x_pos + 20;
  47.     end
  48.     else
  49.     begin
  50.       //if pword[1] <> 20 then
  51.       begin
  52.         text := TTF_RenderUNICODE_blended(engfont, @pword[1], TSDL_Color(Color));
  53.         dest.x := x_pos + 10;
  54.         dest.y := y_pos + 4;
  55.         nullcolor := getpixel(text, 0, 0);
  56.         for i1 := 0 to text.h - 1 do
  57.           for i2 := 0 to text.w - 1 do
  58.           begin
  59.             color1 := getpixel(text, i2, i1);
  60.             color2 := getpixel(sur, dest.x + i2, dest.y + i1);
  61.             if color1 <> nullcolor then
  62.             begin
  63.               pix1 := color1 and $FF;
  64.               pix5 := color2 and $FF;
  65.               pix2 := color1 shr 8 and $FF;
  66.               pix6 := color2 shr 8 and $FF;
  67.               pix3 := color1 shr 16 and $FF;
  68.               pix7 := color2 shr 16 and $FF;
  69.               pix4 := color1 shr 24 and $FF;
  70.               pix8 := color2 shr 24 and $FF;
  71.               pix1 := (alpha * pix1 + (255 - alpha) * pix5) div 255;
  72.               pix2 := (alpha * pix2 + (255 - alpha) * pix6) div 255;
  73.               pix3 := (alpha * pix3 + (255 - alpha) * pix7) div 255;
  74.               pix4 := (alpha * pix4 + (255 - alpha) * pix8) div 255;
  75.               color3 := pix1 + pix2 shl 8 + pix3 shl 16 + pix4 shl 24;
  76.             end
  77.             else
  78.               color3 := color2;
  79.             putpixel(sur, dest.x + i2, dest.y + i1, color3);
  80.           end;
  81.       end;
  82.       x_pos := x_pos + 10;
  83.     end;
  84.     SDL_FreeSurface(text);
  85.   end;

  86. end;
复制代码
以上就是显示半透明的文字。这两个半透明显示的子程的alpha参数范围都是0到255。

说完了半透明显示,再来说说缩放和旋转。如果我们自己写代码的话就太麻烦了。还好SDL有一个扩展库SDL_gfx。它提供了一些功能,可以实现对整个surface的旋转,缩放等功能。
下面是几个缩放旋转的函数

zoomSurface(src : PSDL_Surface; zoomx : double; zoomy : double; smooth : integer ) : PSDL_Surface;
缩放表面大小,各参数意义:
   src:源表面
   zoomx:是x方向放大倍数
   zoomy:是y方向放大倍数
   smooth:值为0是普通模式,值为1时反锯齿

rotozoomSurface( src : PSDL_Surface; angle : double; zoom : double; smooth : integer ) : PSDL_Surface;
缩放并旋转,各参数意义:
   src:原表面
   angle:向左旋转的角度
   zoom:缩放的倍数
   smooth:值为0是普通模式,值为1时反锯齿

rotozoomSurfaceXY( src : PSDL_Surface; angle : double; zoomx : double; zoomy : double; smooth : integer ) : PSDL_Surface;
与上面的函数唯一区别是把XY方向缩放倍数给分开了。

讨论这些的主要原因是,金群的大部分图片都不是很华丽,但是我们可以通过这些功能的组合实现稍微华丽的效果,让游戏效果越来越好。

附件竟然要小于0.512KB。只好把东西上传到别的地方,下载地址http://www.rayfile.com/files/74d ... -878d-0015c55db73d/ 压缩包包括SDL_gfx.pas和SDL_gfx.dll。

[ 本帖最后由 哄你入眠 于 2010-4-16 11:54 编辑 ]

评分

参与人数 1声望 +14 收起 理由
KA + 14 高手

查看全部评分

【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2010-4-15 17:46 | 显示全部楼层
半透明文字的麻烦了~

既然text是一个surface,那用回上面的SDL_SetAlpha不就结了~

自己写的东西干嘛又不会用了~

[发帖际遇]: winson7891在老顽童处骗取《养蜂秘法》,翻印成《如何饲养文化型蜜蜂》出版后获利银两11。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2010-4-15 17:58 | 显示全部楼层
额……我帖子里说了,文字的surface无法设置透明度的。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2010-4-15 18:02 | 显示全部楼层
格式一样~为什么不可以~

PS:我也没试过~表拍~
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2010-4-15 18:07 | 显示全部楼层
呵呵,那你试试就知道了,不一样的。
好像是PSDL_surface.format.AMask这个参数不一样,但究竟是不是这个我也没具体研究过。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2010-4-15 22:48 | 显示全部楼层
对不起,刚才抽了~

刚刚想起,其实那啥~SetAlpha的作用只是改变surface.format.alpha的值,从而改变整个表面的半透明度

如果任何图的本身就有半透明,那么此设置似乎无效~

例如ttf的文字(特别是平滑的),绝大部分都带半透明的,再例如那些修过边带变透明的png图片

似乎都无法使SetAlpha起用

嗯,我在这方面也没有多少经验,但似乎是这样~

[发帖际遇]: 韦小宝得知winson7891擒获了冯锡范,大喜过望,奖励银两17两。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2010-4-15 23:38 | 显示全部楼层
那可能吧,要是这样那么对图片也每个像素处理。主要是多尝试尝试,我也就是给个思路,具体有什么问题就欢迎大家讨论了

[发帖际遇]: 哄你入眠拍丁春秋的马屁结果拍到马腿上,被丁春秋打伤,失去医疗费银两6两。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2010-4-16 10:42 | 显示全部楼层
图片半透明显示已经更正。先判断图像需不需要对每个像素进行处理,然后根据判断结果进行相应处理。
如果还有问题请大家提出,我们一起研究研究

[发帖际遇]: 哄你入眠拍丁春秋的马屁,获赠金钱银两1两。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。

本版积分规则

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

GMT+8, 2024-12-23 04:40

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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