PDA

View Full Version : Modifying a DXimagelist bitmap



Damot
14-09-2004, 05:11 PM
Hi all,

I have a DXimagelist bitmap that I?¢_Tm drawing a radar display panel on. I?¢_Tm then drawing this onto my DXdraw surface every frame (overwriting some other stuff).

But almost every frame I want to make *some* changes to this radar panel How do I quicky and safely modify the bitmap in the DXimagelist?

If I write to DXimagelist.items[whatever].picture.bitmap.canvas it doesn?¢_Tt appear to update until I call DXimagelist.items[whatever].restore and this is *very* slow. I?¢_Tm assuming it makes some major changes to the whole Dximagelist.

Any ideas how to do this?

Oh, I don?¢_Tt want to draw the whole radar straight onto the DXdraw surface because most of it doesn?¢_Tt change every frame. Also the changes I want to make to the radar don?¢_Tt occur every frame, so there?¢_Ts no point drawing them every frame either, hence the need to just update the radar in the DXimagelist when necessary

Thanks!

Traveler
14-09-2004, 08:33 PM
Why not use an extra surface that isn't located in the dximagelist?

You can use the origional radar image from the dximagelist, create a new surface from it and then use that to make changes and eventually draw it on the canvas.

Damot
14-09-2004, 10:22 PM
Why not use an extra surface that isn't located in the dximagelist?

You can use the origional radar image from the dximagelist, create a new surface from it and then use that to make changes and eventually draw it on the canvas.

I'm not exactly sure what you mean "extra surface.." I'm afraid I'm only really experienced with the normal DelpiX components.

Can you give me an example?

ijcro
15-09-2004, 06:47 AM
You can try my code:

put following code to OnCreate of the form:var
D:TDIB;
I : TPictureCollectionItem;
....

D := TDIB.Create; //instance of DIB
Try
{Picture and color}
D.SetSize(100,100,24); //it is square
D.Canvas.Brush.Color := RGB($FF,$33,$22); //with this color
D.Canvas.FillRect(Bounds(0,0,100,100)); //render it
{new item for DXImageList}
I := TPictureCollectionItem.Create(DXImageList1.Items);
{picture assigned here}
I.Picture.Graphic := D; //OR better --> I.Picture.Assign(D);
{name for ident}
I.Name := 'Test2';
{and specific set up here}
I.Transparent := False;
Finally
D.Free; //freeing of DIB
End

using this picture see (bar on screen)DXImageList1.Items.Find('Test2').DrawAlpha( DXDraw1.Surface,Bounds(200,0,100,DXDraw1.Display.H eight),0,128);


Is it right ?

Damot
15-09-2004, 08:32 AM
You can try my code:



Thanks for the reply.

I think I see what you?¢_Tre doing there, but I?¢_Tm not sure how that helps my situation.

Tdib.create makes a bitmap in memory rather than video memory doesn?¢_Tt it?

I know you're then assigning it to a dximagelist but I want to modify the image every frame.

Sorry if I'm misunderstanding here.

ijcro
15-09-2004, 02:20 PM
A/ You can pred-render frame series and store it into pattern. And drawing do by pattern of image
B/ You can make own Surface (in OnCreate of form) and directly draw on this. After painting blit surface into via DXDraw.Draw()

Is it well?

Useless Hacker
15-09-2004, 11:37 PM
You can use a TDirectDrawSurface instead of a TPictureCollectionItem. You can then draw onto the surface the same way as you would draw onto the backbuffer (i.e. DXDraw.Surface); then draw the surface onto the backbuffer each frame.

Traveler
16-09-2004, 08:07 AM
Here's some sample code of what I meant earlier. I haven't checked the code, and so I'm not entirely sure if its correct, but you'll hopefully get some ideas from it.


var
Form1: TForm1;
radarImg: TDirectDrawSurface;


implementation

{$R *.DFM}

procedure doRadarStuffHere()
begin
//do your radar drawing stuff in here like, i dunno draw pixels
//for every enemy you see or something like that
radarImg.Canvas.Pixels[30,20] := clyellow;
radarImg.Canvas.release;
end;

procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
DXDraw1.surface.fill(0);
doRadarStuffHere();
//instead of drawing the radarimg from the dximagelist, we draw the new
//radarimg, we just changed.
DXDraw1.Surface.Draw(10, 10, radarImg.ClientRect, radarImg, false);
DXDraw1.Flip;
end;

procedure TForm1.DXDraw1Initialize(Sender: TObject);
begin
//create new surface
radarImg:= TDirectDrawSurface.Create(DXDraw1.DDraw);
//and load the radarimage from the dximagelist
radarImg.LoadFromGraphic(dximagelist1.Items.Find['origionalRadarImg'].Picture.Graphic);
dxtimer1.Enabled:=true;
end;


(Note, the drawing pixel part on the radar image is just a quick example, and isn't exactly fast.)

Hope this helps

Damot
16-09-2004, 05:17 PM
Here's some sample code of what I meant earlier. I haven't checked the code, and so I'm not entirely sure if its correct, but you'll hopefully get some ideas from it......
....
Hope this helps

Wonderful! Thanks very much. I was able to made it work really nicely now.

Out of interest, why is the "radarImg:= TDirectDrawSurface.Create(DXDraw1.DDraw);" made in "DXDraw1Initialize"?

Is it not possible to create a new surface elsewhere? (I tried and it caused an error). I'm assuming it's possible, perhaps I just did something wrong.

Anyway, thanks again for your help!

Traveler
17-09-2004, 08:02 AM
No it is not possible, you can only create new surfaces during or after the onInitialize event.

Damot
07-10-2004, 05:40 PM
No it is not possible, you can only create new surfaces during or after the onInitialize event.

Thanks for your help, but can you help me with a new problem?

When I change from windowed mode to fullscreen (during the game) or use ALT-TAB to switch applications, the surface seems to disappear completely.

What's the correct way to handle that?

TIA!

Traveler
08-10-2004, 10:26 AM
Alt tabbing has always been a bit of a pain in DelphiX. It is not impossible though. In one of the spritedemos (shootinggame iirc) there's samplecode of how to switch to fullscreen and/or return again.
If I'm not mistaken it stops the timer, does a (re)storewindow call, sets fullscreenproperty and starts the timer again.

Hope this works for you

sam.chung
08-10-2004, 03:38 PM
This is code I used to deal with it. I don't know if it is well, but it work

var
bIniOnStart: Boolean;

procedure TFmMain.FormCreate(Sender: TObject);
begin
bIniOnStart := True;
end;

procedure TFmMain.DXTimer1Deactivate(Sender: TObject);
begin
bIniOnStart := False;
end;

procedure TFmMain.DXTimer1Activate(Sender: TObject);
begin
if not bIniOnStart then begin
DXDraw1.Initialize;
end;
end;

Damot
08-10-2004, 05:47 PM
Alt tabbing has always been a bit of a pain in DelphiX. It is not impossible though. In one of the spritedemos (shootinggame iirc) there's samplecode of how to switch to fullscreen and/or return again.
If I'm not mistaken it stops the timer, does a (re)storewindow call, sets fullscreenproperty and starts the timer again.

Hope this works for you

Thanks. I didn't make the problem very clear. I've managed to get the windowed/fullscreen changing okay but the contents of the radar surface (like in your example) seemed to disappear.

So I had to put a new "radarImg.LoadFromGraphic..." into the dxdraw.onsurfacerestore

Not sure if that's the correct thing to do but it works!