本帖最后由 weyl 于 2012-12-23 19:51 编辑
这次对遮挡的修改大量依赖这个子程.同时增加了混合颜色效果.
推荐使用, 建议其余子程对此封装.- //这是改写的绘制RLE8图片程序, 增加了选调色板, 遮挡控制, 亮度, 半透明, 混合色等
- //colorPanel: Pchar; 调色板的指针. 某些情况下需要使用静态调色板, 避免静态图跟随水的效果
- //num, px, py: integer; 图片的编号和位置
- //Pidx: Pinteger; Ppic: PByte; 图片的索引和内容的资源所在地
- //RectArea: Pchar; 画图的范围, 所指向地址应为连续4个integer, 表示一个矩形, 仅图片的部分或全部会出现在这个矩形内才画
- //Image: PChar; widthI, heightI, sizeI: integer; 映像的位置, 尺寸, 每单位长度. 如果Img不为空, 则会将图画到这个镜像上, 否则画到屏幕
- //shadow, alpha: integer; 图片的暗度和透明度, 仅在画到屏幕上时有效
- //BlockImageW: PChar; 大小与场景和战场映像相同. 如果此地址不为空, 则会记录该像素的场景深度depth, 用于遮挡计算.
- //BlockScreenR: PChar; widthR, heightR, sizeR: integer; 该映像应该与屏幕像素数相同, 保存屏幕上每一点的深度值
- //depth: integer; 所画物件的深度, 即场景坐标 x + y, 深度高的物件会遮挡深度低的.
- //当BlockImageW不为空时, 将该值写入BlockImageW, 如果该值超出范围(0~128), 会根据图片的y坐标计算一个,
- //但是需注意计算值在场景内包含高度的情况下是不准确的.
- //当Image为空, 即画到屏幕上时, 同时BlockScreenR不为空, 如果所绘像素的已有深度大于该值, 则按照alpha绘制该像素
- //即该值起作用的机会有两种: Image不为空(到映像), 且BlockImageW不为空; 或者Image为空(到屏幕), 且BlockScreenR不为空.
- //如果在画到屏幕时避免该值起作用, 可以设为128, 这是深度理论上的最大值(实际达不到)
- //MixColor: Uint32; MixAlpha: integer 图片的混合颜色和混合度, 仅在画到屏幕上时有效
- procedure DrawRLE8Pic3(colorPanel: Pchar; num, px, py: integer; Pidx: Pinteger; Ppic: PByte; RectArea: Pchar; Image: PChar; widthI, heightI, sizeI: integer; shadow, alpha: integer;
- BlockImageW: PChar; BlockScreenR: PChar; widthR, heightR, sizeR: integer; depth: integer; MixColor: Uint32; MixAlpha: integer);
- var
- w, h, xs, ys: smallint;
- offset, length, p, isAlpha, lenInt: integer;
- l, l1, ix, iy, pixdepth: integer;
- pix, pix1, pix2, pix3, pix4, colorin, color1, color2, color3, color4: Uint32;
- begin
- if num = 0 then
- offset := 0
- else
- begin
- inc(Pidx, num - 1);
- offset := Pidx^;
- end;
- Inc(Ppic, offset);
- w := Psmallint((Ppic))^;
- Inc(Ppic, 2);
- h := Psmallint((Ppic))^;
- Inc(Ppic, 2);
- xs := Psmallint((Ppic))^;
- Inc(Ppic, 2);
- ys := Psmallint((Ppic))^;
- Inc(Ppic, 2);
- pixdepth := 0;
- lenInt := sizeof(integer);
- if (px - xs + w >= pint(RectArea)^) and (px - xs < pint(RectArea)^ + pint(RectArea + lenInt * 2)^)
- and (py - ys + h >= pint(RectArea + lenInt)^) and (py - ys < pint(RectArea + lenInt)^ + pint(RectArea + lenInt * 3)^) then
- begin
- for iy := 1 to h do
- begin
- l := Ppic^;
- inc(Ppic, 1);
- w := 1;
- p := 0;
- for ix := 1 to l do
- begin
- l1 := Ppic^;
- inc(Ppic);
- if p = 0 then
- begin
- w := w + l1;
- p := 1;
- end
- else if p = 1 then
- begin
- p := 2 + l1;
- end
- else if p > 2 then
- begin
- p := p - 1;
- if (w - xs + px >= pint(RectArea)^) and (iy - ys + py >= pint(RectArea + lenInt)^)
- and (w - xs + px < pint(RectArea)^ + pint(RectArea + lenInt * 2)^) and (iy - ys + py < pint(RectArea + lenInt)^ + pint(RectArea + lenInt * 3)^) then
- begin
- if image = nil then
- begin
- pix := sdl_maprgb(screen.format, puint8(colorPanel + l1 * 3)^ * (4 + shadow), puint8(colorPanel + l1 * 3 + 1)^ * (4 + shadow), puint8(colorPanel + l1 * 3 + 2)^ * (4 + shadow));
- if (alpha <> 0) then
- begin
- if (BlockScreenR = nil) then
- begin
- isAlpha := 1;
- end
- else
- begin
- if ((w - xs + px) < widthR) and ((iy - ys + py) < heightR) then
- begin
- pixdepth := pint(BlockScreenR + ((w - xs + px) * heightR + (iy - ys + py)) * sizeR)^;
- if pixdepth > depth then
- begin
- isAlpha := 1;
- end
- else
- isAlpha := 0;
- end;
- end;
- if (isAlpha = 1) and (Alpha < 100) then
- begin
- colorin := getpixel(screen, w - xs + px, iy - ys + py);
- pix1 := pix and $FF;
- color1 := colorin and $FF;
- pix2 := pix shr 8 and $FF;
- color2 := colorin shr 8 and $FF;
- pix3 := pix shr 16 and $FF;
- color3 := colorin shr 16 and $FF;
- pix4 := pix shr 24 and $FF;
- color4 := colorin shr 24 and $FF;
- pix1 := (alpha * color1 + (100 - alpha) * pix1) div 100;
- pix2 := (alpha * color2 + (100 - alpha) * pix2) div 100;
- pix3 := (alpha * color3 + (100 - alpha) * pix3) div 100;
- pix4 := (alpha * color4 + (100 - alpha) * pix4) div 100;
- pix := pix1 + pix2 shl 8 + pix3 shl 16 + pix4 shl 24;
- end;
- end;
- if mixAlpha <> 0 then
- begin
- colorin := MixColor;
- pix1 := pix and $FF;
- color1 := colorin and $FF;
- pix2 := pix shr 8 and $FF;
- color2 := colorin shr 8 and $FF;
- pix3 := pix shr 16 and $FF;
- color3 := colorin shr 16 and $FF;
- pix4 := pix shr 24 and $FF;
- color4 := colorin shr 24 and $FF;
- pix1 := (mixAlpha * color1 + (100 - mixAlpha) * pix1) div 100;
- pix2 := (mixAlpha * color2 + (100 - mixAlpha) * pix2) div 100;
- pix3 := (mixAlpha * color3 + (100 - mixAlpha) * pix3) div 100;
- pix4 := (mixAlpha * color4 + (100 - mixAlpha) * pix4) div 100;
- pix := pix1 + pix2 shl 8 + pix3 shl 16 + pix4 shl 24;
- end;
- if (Alpha < 100) or (pixdepth <= depth) then
- putpixel(screen, w - xs + px, iy - ys + py, pix);
- end
- else
- begin
- if ((w - xs + px) < widthI) and ((iy - ys + py) < heightI) then
- begin
- if (BlockImageW <> nil) then
- begin
- if (depth < 0) or (depth > 128) then
- depth := py div 9 - 1;
- Pint(BlockImageW + ((w - xs + px) * heightI + (iy - ys + py)) * sizeI)^ := depth;
- end;
- Pint(image + ((w - xs + px) * heightI + (iy - ys + py)) * sizeI)^ :=
- sdl_maprgb(screen.format, puint8(colorPanel + l1 * 3)^ * (4 + shadow), puint8(colorPanel + l1 * 3 + 1)^ * (4 + shadow), puint8(colorPanel + l1 * 3 + 2)^ * (4 + shadow));
- end;
- end;
- end;
- w := w + 1;
- if p = 2 then
- begin
- p := 0;
- end;
- end;
- end;
- end;
- end;
- end;
复制代码 |