PDA

View Full Version : Transparent sprites in Jedi SDL



Smotsholle
23-09-2005, 10:43 AM
I'm working with the sprite-engine using delphi jedi SDL.

In the future I want to add transparent sprites to the engine.
Does the Sprite-engine support this in any way, because I couldn't find it.
If it isn't possible. Could anyone tell me how I can add this to the engine?

I'm not too familiar with sprite transparency, but I heard it is possible.

Thanks in advance.

Paulius
23-09-2005, 11:37 AM
It uses magenta (the least likely color you?¢_Td want to use) as a color key, so what is of that color will be transparent. If you mean not transparency, but translucency then you?¢_Tll need to add SDL_SetAlpha to it.

Smotsholle
23-09-2005, 02:48 PM
Sorry, I meant translucency.... In real life it's the same, but I forgot it isn't in programming :P

Anyways, Thanks for the help, I'll look into it.
I'll add the sprite-engine with a translucency-variable. I assume it's an integer value with 0 for being solid and 100 for being invisible, but I should be able to figure that out.

Thanks again for the help. :D

technomage
23-09-2005, 03:20 PM
I seem to remember that you need to set some color key flags on the surface as well and I think the color can get defined by SDL_ColorKey. I could be wrong though.

Dean

WILL
23-09-2005, 11:34 PM
I had submitted a few alpha blending draw routeens for JEDI-SDL some time ago... submitted it to savage for inclusion into the final 1.0 release. Though, they didn't quite make it there yet. ;) ("He's a busy bloke", I believe thats proper UK-nese?)

But here is a copy of my personal 'special edition' of sdlutils.pas in JEDI-SDL.


EDIT: Here is a clip from my own personal copy of sdlutils.pas.

var
{--- Trig Lookup Tables ---}
degSIN,
degCOS,
degTAN,
degArcCOS,
degArcSIN,
degArcTAN: Array[-360 .. 360] of Extended;


{Pre-Calculate SIN and COS Tables}
procedure PreCalculate_Trig;

The above to be placed in the interface portion of your unit.

Then you'll need this procedure:
{Pre-Calculate SIN and COS Tables}
procedure PreCalculate_Trig;
var i: Integer;
begin
for i := Low(degSIN) to High(degSIN) do
degSIN[i] := sin(i * Pi_Div_180);
for i := Low(degCOS) to High(degCOS) do
degCOS[i] := cos(i * Pi_Div_180);
for i := Low(degTAN) to High(degTAN) do
degTAN[i] := tan(i * Pi_Div_180);
end;


and be sure to either add this to your unit's main code block or execute it somewhere in your project's code before trying to use the function.

begin
PreCalculate_Trig;
end.

Now you can add this function that will allow you to draw a sprite rotated(in degrees) and alpha blended.

procedure SDL_RotateDeg_Alpha(DstSurface, SrcSurface: PSDL_Surface; SrcRect: PSDL_Rect;
DestX, DestY, OffsetX, OffsetY: Integer; Angle: Integer;
Alpha: UInt8);
var
aSin, aCos: Single;
MX, MY, DX, DY, NX, NY, SX, SY, OX, OY, Width, Height, TX, TY, RX, RY, ROX, ROY: Integer;
SrcColor, DstColor: UInt32;
srcRR, srcGG, srcBB, dstRR, dstGG, dstBB: UInt8;
TempTransparentColour: UInt32;
MAXX, MAXY: Integer;
begin
// Rotate the surface to the target surface.
TempTransparentColour := SrcSurface.format.colorkey;

maxx := DstSurface.w;
maxy := DstSurface.h;
aCos := degCOS[Angle];
aSin := degSIN[Angle];

Width := round(abs(srcrect.h * acos) + abs(srcrect.w * asin));
Height := round(abs(srcrect.h * asin) + abs(srcrect.w * acos));

OX := Width shr 1;
OY := Height shr 1;
MX := (srcRect.x + (srcRect.x + srcRect.w)) shr 1;
MY := (srcRect.y + (srcRect.y + srcRect.h)) shr 1;
ROX := (-(srcRect.w shr 1)) + Offsetx;
ROY := (-(srcRect.h shr 1)) + OffsetY;
Tx := ox + round(ROX * aSin - ROY * aCos);
Ty := oy + round(ROY * aSin + ROX * aCos);
SX := 0;
for DX := DestX - TX to DestX - TX + (width) do
begin
inc(SX);
SY := 0;
for DY := DestY - TY to DestY - TY + (Height) do
begin
if ((DX > 0) and (DX < MAXX)) and
((DY > 0) and (DY < MAXY)) then
begin
RX := SX - OX;
RY := SY - OY;
NX := mx + Round(RX * aSin + RY * aCos); //
NY := my + Round(RY * aSin - RX * aCos); //

if (NX >= srcRect.x) and (NX <= srcRect.x + srcRect.w) then
begin
if (NY >= srcRect.y) and (NY <= srcRect.y + srcRect.h) then
begin
SrcColor := SDL_GetPixel(SrcSurface, NX, NY);
if (SrcColor <> TempTransparentColour) then
begin
SDL_GetRGB(SrcColor, SrcSurface.format, @srcRR, @srcGG, @srcBB);

DstColor := SDL_GetPixel(DstSurface, DX, DY);
SDL_GetRGB(DstColor, DstSurface.format, @dstRR, @dstGG, @dstBB);

SDL_PutPixel(DstSurface, DX, DY,
SDL_MapRGB(DstSurface.format,
(Alpha * (srcRR - dstRR)) shr 8 + dstRR,
(Alpha * (srcGG - dstGG)) shr 8 + dstGG,
(Alpha * (srcBB - dstBB)) shr 8 + dstBB));
end;
end;
end;
end;
inc(SY);
end;
end;
end;


Obviously I'm using pre-calculations for this, which is a smart move considering that you might end up using a function like this, depending on the type of game your coding, a lot durring EACH frame.

Paulius
24-09-2005, 07:50 AM
WILL, you've posted this before, but as I see, didn't take any of my feedback into account at all :( , here goes again:
You're going the wrong way, in X first and Y second, it should be the other way around so memory access is sequential and pleasing for you're cash.
using precalculated values just once in a procedure is noting, you might as well you real functions for more precision
Rounding in the innermost loop is costly, round aCos, aSin outside of it multiplied by a power of two, and in the loop just use fixed point shifts
Function calls in the innermost loop is bad, extract those put/get routines and better yet make different versions of ypu're procedure with 32bit->32bit, 8bit -> 8bit, etc. and in the main one check surface formats and call an appropriate one.

Smotsholle
28-09-2005, 11:20 AM
I've tried ajusting the code. The problem is.... if the alpha I set goes anywhere below 255, the image simply becomes invisible :(

Can someone maybe post some sample code here on how to get it working? I know the oxygene demo uses it and I think the problem lies with the surface layer. But I can't seem to figure out how to fix it without causing access violations.