实在乱七八糟,不知道怎么说起。就先来讨论一下怎么实现图片(非RLE8格式)的半透明显示,REL8格式半透明乌鸦大大曾经写过,就不说了~~
在SDL中可以对surface设置透明度,用到的函数是function SDL_SetAlpha(surface: PSDL_Surface; flag: UInt32; alpha: UInt8): Integer; 用法不算难,只要看看实例中怎么用就应该能明白了。
下面的代码是显示一个半透明的png,jpeg等图片的代码:- procedure display_img(file_name: PChar; x, y: integer; Alpha: Uint8); overload;
- var
- image: PSDL_Surface;
- dest: TSDL_Rect;
- pix1,pix2,pix3,pix4,pix5,pix6,A,Amask, color1, color2, color3: Cardinal;
- i1, i2: integer;
- begin
- if fileexists(file_name) then
- begin
- image := IMG_Load(file_name);
- if (image = nil) then
- begin
- MessageBox(0, PChar(Format('Couldn''t load %s : %s',
- [file_name, SDL_GetError])), 'Error', MB_OK or MB_ICONHAND);
- exit;
- end;
- dest.x := x;
- dest.y := y;
- Amask := image.format.AMask;
- if AMask = 0 then
- begin
- SDL_SetAlpha(image, SDL_SRCALPHA, alpha); //alpha是透明度,范围是0到255
- if (SDL_BlitSurface(image, nil, screen, @dest) < 0) then
- MessageBox(0, PChar(Format('BlitSurface error : %s', [SDL_GetError])), 'Error', MB_OK or MB_ICONHAND);
- //SDL_UpdateRect(screen, 0, 0, image.w, image.h);
- end
- else
- begin
- for i1 := 0 to image.h - 1 do
- for i2 := 0 to image.w - 1 do
- begin
- color1 := getpixel(image, i2, i1);
- A := (color1 shr image.format.Ashift) and $FF;
- if A <> 0 then
- begin
- testA := A;
- A := A * alpha div 255;
- pix1 := color1 shr image.format.Rshift and $FF;
- pix2 := color1 shr image.format.Gshift and $FF;
- pix3 := color1 shr image.format.Bshift and $FF;
- color2 := getpixel(screen, x + i2, y + i1);
- pix4 := color2 shr screen.format.Rshift and $FF;
- pix5 := color2 shr screen.format.Gshift and $FF;
- pix6 := color2 shr screen.format.Bshift and $FF;
- pix1 := (A * pix1 + (255 - A) * pix4) div 255;
- pix2 := (A * pix2 + (255 - A) * pix5) div 255;
- pix3 := (A * pix3 + (255 - A) * pix6) div 255;
- color3 := pix1 shl screen.format.Rshift + pix2 shl screen.format.Gshift + pix3 shl screen.format.Bshift;
- putpixel(screen, i2 + x, i1 + y, color3);
- end;
- end;
- end;
- SDL_FreeSurface(image);
- end;
- end;
复制代码 bmp图片半透明的显示也是相同道理,在这里就不写了。
图片说完了,下面说说半透明显示文字吧,文字和图片的处理不太一样,主要是因为通过TTF_RenderUNICODE_blended得到的surface无法设置透明度。那么我们就用最基础的方法,对每个像素进行操作。下面改写一下原来的DrawText函数。- procedure DrawText(sur: PSDL_Surface; word: PUint16; x_pos, y_pos: integer; color: Uint32; alpha: Uint8); overload;
- var
- dest: TSDL_Rect;
- i1, i2, alpha: integer;
- pword: array[0..2] of Uint16;
- nullcolor, color1, color2, color3, pix1, pix2, pix3, pix4, pix5, pix6, pix7, pix8: Uint32;
- begin
- pword[0] := 32;
- pword[2] := 0;
- dest.x := x_pos;
- while word^ > 0 do
- begin
- pword[1] := word^;
- inc(word);
- if pword[1] > 128 then
- begin
- text := TTF_RenderUNICODE_blended(font, @pword[0], TSDL_Color(Color));
- dest.x := x_pos - 10;
- dest.y := y_pos;
- nullcolor := getpixel(text, 0, 0);
- for i1 := 0 to text.h - 1 do
- for i2 := 0 to text.w - 1 do
- begin
- color1 := getpixel(text, i2, i1);
- color2 := getpixel(sur, dest.x + i2, dest.y + i1);
- if color1 <> nullcolor then
- begin
- pix1 := color1 and $FF;
- pix5 := color2 and $FF;
- pix2 := color1 shr 8 and $FF;
- pix6 := color2 shr 8 and $FF;
- pix3 := color1 shr 16 and $FF;
- pix7 := color2 shr 16 and $FF;
- pix4 := color1 shr 24 and $FF;
- pix8 := color2 shr 24 and $FF;
- pix1 := (alpha * pix1 + (255 - alpha) * pix5) div 255;
- pix2 := (alpha * pix2 + (255 - alpha) * pix6) div 255;
- pix3 := (alpha * pix3 + (255 - alpha) * pix7) div 255;
- pix4 := (alpha * pix4 + (255 - alpha) * pix8) div 255;
- color3 := pix1 + pix2 shl 8 + pix3 shl 16 + pix4 shl 24;
- end
- else
- color3 := color2;
- putpixel(sur, dest.x + i2, dest.y + i1, color3);
- end;
- x_pos := x_pos + 20;
- end
- else
- begin
- //if pword[1] <> 20 then
- begin
- text := TTF_RenderUNICODE_blended(engfont, @pword[1], TSDL_Color(Color));
- dest.x := x_pos + 10;
- dest.y := y_pos + 4;
- nullcolor := getpixel(text, 0, 0);
- for i1 := 0 to text.h - 1 do
- for i2 := 0 to text.w - 1 do
- begin
- color1 := getpixel(text, i2, i1);
- color2 := getpixel(sur, dest.x + i2, dest.y + i1);
- if color1 <> nullcolor then
- begin
- pix1 := color1 and $FF;
- pix5 := color2 and $FF;
- pix2 := color1 shr 8 and $FF;
- pix6 := color2 shr 8 and $FF;
- pix3 := color1 shr 16 and $FF;
- pix7 := color2 shr 16 and $FF;
- pix4 := color1 shr 24 and $FF;
- pix8 := color2 shr 24 and $FF;
- pix1 := (alpha * pix1 + (255 - alpha) * pix5) div 255;
- pix2 := (alpha * pix2 + (255 - alpha) * pix6) div 255;
- pix3 := (alpha * pix3 + (255 - alpha) * pix7) div 255;
- pix4 := (alpha * pix4 + (255 - alpha) * pix8) div 255;
- color3 := pix1 + pix2 shl 8 + pix3 shl 16 + pix4 shl 24;
- end
- else
- color3 := color2;
- putpixel(sur, dest.x + i2, dest.y + i1, color3);
- end;
- end;
- x_pos := x_pos + 10;
- end;
- SDL_FreeSurface(text);
- end;
- 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 编辑 ] |