View Full Version : help with Bitblt plz someone tht also knows vb lol.

15-06-2004, 02:46 PM
Ok in vb i drew sprites ina game like this.

Clear Form
BitBlt Mask
BitBlt Picture
Refresh Form

1.Delphi has no .Cls or Clear methods nor does PaintBox.
2.None of delphi's components have a autoredraw property.

Does anybody know how i can do this very same thign in delphi 7?

i can BitBlt and Refresh at da end but it flickers like crazy.

EDIT: sorry bout the double post dont know what happened there.

15-06-2004, 05:18 PM
You might want to investigate the "DoubleBuffered" property - just put the following line of code into your form's OnCreate event:

DoubleBuffered := True;

If you do that then you get the best effect by doing your drawing in the relevant OnPaint procedure. You could use a timer set to refresh the relevant object (the form, a paintbox, or whatever you're drawing onto). Check out the Repaint, Refresh and Invalidate methods...

(Side note: TTimer ain't too accurate, but it'll do for a start.)

Now, getting sprites is pretty straightforward - you don't need to mask out the objects manually. Instead, you can just load up the object into a TBitmap and set the Transparent property to true (and maybe the TransparentColor beforehand, if you want). This means that the sprite will be drawn transparently if you use the Draw method for the relevant canvas (e.g. Canvas.Draw for your form or Paintbox1.Canvas.Draw if you're using a paintbox - you get the idea).

I'll send you an email with source for a very basic example of this. As a side don't - don't expect brilliant speed using bog-standard Windows drawing, but I guess you wouldn't expect that anyway. Once you want to get better results, look to something else like DirectX, OpenGL or Direct3D.

EDIT: or at least, I'll send you a basic example once I get your email address. Doh!

15-06-2004, 05:25 PM
im wondering if using the OnPaint event is a little overkill as i only wish to redraw sprite/sprites when necessary.

15-06-2004, 05:43 PM
Procedure PlayDraw;
//Now blit them into screen combined for transparency effect.
BitBlt(FrmMain.Canvas.Handle, ShipX, ShipY, ShipMask.Width, ShipMask.Height, ShipMask.Canvas.Handle, 0, 0, SRCAND);
BitBlt(FrmMain.Canvas.Handle, ShipX, ShipY, Ship.Width, Ship.Height, Ship.Canvas.Handle, 0, 0, SRCPAINT);

This is what i have atm ive tryed many various combinations of using InvaliDate, ReFresh and the Repaint method. This is the only one that seems to flicker less but still flickery. I also set the forms doublebuffered to true in the OnCreate event.

This procedure is being called in the OnKeyDown event of the form just checking for left keypress/hold for testing and it flickers pretty bad but not as worse as before lol.

Harry Hunt
15-06-2004, 06:04 PM
Don't use Repaint, Invalidate, etc. They will always cause some serious flickering and they're not intended for just erasing the background of a canvas either.

To properly erase the background, try this:

with Canvas do
Pen.Color := Form1.Color;
Brush.Color := Form1.Color;

To completely avoid flickering, draw everything on a buffer first and then draw it onto the canvas. Example:

Buffer: TBitmap;

procedure TForm1.FormCreate(Sender: TObject);
Buffer := TBitmap.Create;
Buffer.Width := Form1.ClientWidth;
Buffer.Height := Form1.ClientHeight;

procedure TForm1.FormClose(Sender: TObject);

procedure TForm1.DrawMyStuff;
with Buffer.Canvas do
Pen.Color := clRed;
Brush.Color := clRed;
Draw(PlayerX, PlayerY, Image1.Picture.Bitmap);

// Flip the buffer onto the screen
Form1.Canvas.Draw(0, 0, Buffer);

procedure TForm1.FormKeyDown(....);
if Key = VK_LEFT then
PlayerX := PlayerX - 1

If you choose to draw directly onto the form canvas instead of the canvas of paint box, you should also handle the OnPaint event. Otherwise the stuff you draw onto the canvas will get lost when someone drags another window over yours.

15-06-2004, 06:08 PM
Ok so maybe i should use a paintbox that's easy enuf except i get error in source code trying to access its properties in my procedure.

Harry Hunt
15-06-2004, 06:09 PM
post the line that gives you the error message...

15-06-2004, 06:10 PM
There's no line its an error in the source code it says like if i type....


the error comes up theres nothing wrong with the source except my proc isnt declared in private or public and doesnt use TForm.Proc.

Harry Hunt
15-06-2004, 06:13 PM
if your procedure is not part of your form, you'll have to access the paintbox like this:

Form1.PaintBox.Width := 200;

Hope I understood what you mean :wink:

15-06-2004, 06:14 PM
i think so although i could declare it i just stick the proc name in private and then slap TForm. infront of proc name in the actual proc :lol:

Harry Hunt
15-06-2004, 06:15 PM
or you put your proc in either private or public and then press CTRL+SHIFT+C. I dunno if this works with all versions of Delphi.

15-06-2004, 06:26 PM
Im still kind of boggled here... im already loading the bitmaps into TBitMap so ur saying im loading into TBitMap then Swapping them to another TBitMap and then finally Blitting to the paintbox.

Harry Hunt
15-06-2004, 06:31 PM
Yep, that's what I'm saying. The concept is called "double buffering" which means that you essentially prepare your "scene" in memory and then when all drawing is completed you "flip" it onto the actual canvas or front buffer. This concept is especially effective when dealing with video memory because "flipping" can be done extremely fast.
The method using TBitmaps is obviously much slower because it works in system memory but it will still prevent flickering quite well.

15-06-2004, 06:33 PM
hmmm well it looks like my only choice your first suggestion did the same as using Repaint method before blitting so i guess ill try the second one and pray :lol:

15-06-2004, 06:45 PM
I think it might be tactics to explain the DoubleBuffered = true line... basically, that enables double-buffering in the OnPaint method of the TWinControl in which it's set. It creates a memory DC and calls the paint event for the specified control using that instead of the normal canvas. You ought to not get any flickering with it in there - if you do, that'd surprise me. But that's why I suggested stuff should be done in OnPaint if you do DoubleBuffered = true;

So, you can do double-buffering by hand with TBitmaps if you want, or you could just use one line of code and be lazy. ;) Of course, though, it's a good idea to use manual double buffering using TBitmaps if you want to update without refreshing the control.

15-06-2004, 06:45 PM
Yay hey no flicker :lol:

15-06-2004, 06:48 PM
hmm it seems to move really slow considering im minusing for going left by 1 would that have something to do with the PixelsPerInch property?

15-06-2004, 06:50 PM
Congrats! It's always a good feeling the first time you manage to squish the flicker!

Now go program something cool and show it off to us! :wink:

15-06-2004, 06:51 PM
hmm it seems to move really slow considering im minusing for going left by 1 would that have something to do with the PixelsPerInch property?
How often do you update the animation? Just based on keypresses or something else (a timer?)?

15-06-2004, 06:52 PM
LOL yeah i remember this bugged me for so long in VB :evil:

I also turned TBitMap for sprite Transparency color to black and to True and removed using the mask id assume this will speed things up if more is added to it 8)

EDIT: I update when necessary like only when something changes thats how i always do things.

15-06-2004, 07:02 PM
I guess that your resolution could be high, maybe - it's surprising how small 1 pixel becomes at higher res. ;) The PixelsPerInch could affect things but I'm not sure if it affects things like you'd expect (I know it affects font sizes and the overall size of the window, at runtime, but does it actually change the pixel sizes in general? Don't think it does but I may stand corrected here).

Does the movement itself seem jerky? Do the graphics seem pretty slow?

Also, watch for moving using the key events (onKeyPress, onKeyDown, or whatever). They may result in not-entirely-smooth movement that's a little stop-start. It may be a better idea to check often whether a key has been pressed at regular intervals and make a note of it, moving then.

Harry Hunt
15-06-2004, 07:04 PM
Of course you could move your sprite in steps > 1 pixel but that could make it a little jerky.
The problem is that the OnKeyDown event is only called at a certain frequency.
If you want fluid motion you'll have to use a timer of some sort.

The DoubleBuffered property is pretty cool and helpful, but I like how using your own TBitmap will give you a lot more control over when you actually redraw your canvas.

15-06-2004, 07:04 PM
hmm im not sure in vb just set mode to pixels it seems to be the default in delphi.

EDIT: this is a lil 15inch CRT monitor im on 800x600 res

CRAP im so stupid thts right move it in more pixels lol sim so lost i swear its 5am :P