Page 1 of 3 123 LastLast
Results 1 to 10 of 24

Thread: Using multiple surfaces

  1. #1

    Using multiple surfaces

    Hi there,

    i am taking my first steps into game programming and have chosen unDelphiX for my first attempts.

    For now, my program only draws tiles from a DXImageList on the DXDraw1.Surface. My approach might not be the most ellegant one, but i am still learning, so here is my problem:


    [pascal]
    TileImageList.Items[i].Draw(DXDraw.Surface, XCoord, YCoord, 0);

    DXDraw.Flip;
    [/pascal]

    Well, this way everything went fine. The program draws the playfield just as i want it to do.
    Now I want to add a user interface as well but instead of rewriting the whole playfield-function and fiddling around with all those relative coordinates to place my tiles it would be much better to draw the tiles on another surface and than place the surface on the right position. This way I could use an absolut coordinate system for the playfield.

    So this is how i tried to do the whole thing:
    [pascal]
    var
    MapSurface : TDirectDrawSurface;

    procedure TfrmTest.DXDrawInitialize(Sender: TObject);
    begin
    MapSurface := TDirectDrawSurface.Create(DXDraw.DDraw);
    end;

    procedure DrawPlayfield;
    begin
    TileImageList.Items[i].Draw(MapSurface, XCoord, YCoord, 0);

    DXDraw.Surface.Draw(0,0, MapSurface, false);
    end;

    procedure DXTimer...
    begin
    DrawPlayfield;
    DXDraw.Flip;
    end;
    [/pascal]

    Unfortunaley this didn't work. I tried both Draw routines with the same result.
    I also replaced the
    TileImageList.Items[i].Draw(MapSurface, XCoord, YCoord, 0);
    with
    Mapsurface.Loadfromgraphic(TileImageList.Item..... .picture.graphic)
    and it drew a lonley tile onto my screen, so i think the problem has something to do with the way I draw on my new surface.

    I hope someone can help me with this.
    thanks in advance
    IaxFenris

  2. #2

    Using multiple surfaces

    hi

    you could try looking at http://www.cerebral-bicycle.co.uk/li...?cat=24&subj=5

    it has a whole load of tutorials about DelphiX ,almost all of which will apply to UnDelphiX.

    Dean
    <A HREF="http://www.myhpf.co.uk/banner.asp?friend=139328">
    <br /><IMG SRC="http://www.myhpf.co.uk/banners/60x468.gif" BORDER="0">
    <br /></A>

  3. #3

    Using multiple surfaces

    thanks for the quick answer technomage!

    The page you mentioned was, and still is, one of the main sources of my unDelphiX knowledge but i couldn't find any answer for my problem, there.

  4. #4

    Using multiple surfaces

    Well it comes down to a couple of things. Firstly, you haven't completely initialized your MapSurface. It needs a Width and Height. So

    [pascal]
    procedure TfrmTest.DXDrawInitialize(Sender: TObject);
    begin
    MapSurface := TDirectDrawSurface.Create(DXDraw.DDraw);
    end;[/pascal]
    should look like this

    [pascal]
    procedure TfrmTest.DXDrawInitialize(Sender: TObject);
    begin
    MapSurface := TDirectDrawSurface.Create(DXDraw.DDraw);
    MapSurface.SetSize(DXDraw.Width,DXDraw.Height);
    end;
    [/pascal]
    which will initialise your MapSurface to the same size as your DXDraw (Change the Width and Height values to whatever is appropriate if you don't want it so big).

    The next problem is with the DrawPlayField procedure.
    [pascal]
    procedure DrawPlayfield;
    begin
    TileImageList.Items[i].Draw(MapSurface, XCoord, YCoord, 0);

    DXDraw.Surface.Draw(0,0, MapSurface, false);
    end; [/pascal] needs to become this...


    [pascal]
    procedure DrawPlayfield;
    var
    Src: TRect;
    begin
    Src.Left:=0;
    Src.Top:=0;
    Src.Right:=MapSurface.Width;
    Src.Bottom:=MapSurface.Height;
    DXImageList1.Items[i].Draw(MapSurface,XCoord,YCoord,0);
    DXDraw.Surface.Draw(0,0,Src,MapSurface,True);
    end;
    [/pascal]

    There are two versions of DXDraw.Surface.Draw and and while trying to get your code to work I found that the one you was using wasn't very effective without a Src RECT so I threw that in and along with the other adjustment seemed to work a treat. If you wish to only draw a part of the MapSurface then adjust the Src values accordingly. Hope this answers your question. Let us know how it goes or if you need me to explain myself better, I don't always make myself clear.


    [EDIT : Few coding mishaps]
    Isometric game development blog http://isoenginedev.blogspot.com/

  5. #5

    Using multiple surfaces

    Hi IaxFenris,

    Let me first welcome you to our PGD. I hope you'll like it here!

    As for your question.
    I can only think of one reason why you would want to draw everything to a temporary surface and then to the main surface, and that is when you have stationary images. Text, for example. Suppose you have all the letters in the alphabet in a single image and you want to to display a sentence from those letters. You could look up the letters one by one in a init procedure and then draw them on a seperate surface, so you can draw it later. It is an option, but really, for todays computers its really no problem to do the lookup at runtime.


    But anway, let me first go through your code.

    [pascal]
    var
    MapSurface : TDirectDrawSurface;

    procedure DrawPlayfield;
    begin
    //Unless you want the coordinates and images from the list to be
    //variable, there really is no need to draw it here over and over again.
    //A single call in the init procedure should do just fine.
    //In fact, if you do it this way, you're wasting valuable cpu power as you
    //could just as well write to the dxdraw surface.
    TileImageList.Items[i].Draw(MapSurface, XCoord, YCoord, 0);

    //this is not correct, it should led to an error as the compiler
    //doesn't know DXDraw. Also, the draw function here requires more
    //parameters
    DXDraw.Surface.Draw(0,0, MapSurface, false);

    //this works better
    Form1.DXDraw1.Surface.Draw(0,0, MapSurface.ClientRect, MapSurface, false);


    end;

    procedure DXTimer...
    begin
    DrawPlayfield;
    DXDraw.Flip;
    end;

    procedure TfrmTest.DXDrawInitialize(Sender: TObject);
    begin
    MapSurface := TDirectDrawSurface.Create(DXDraw.DDraw);
    end;

    [/pascal]

    Up to now the code works perfectly. It compiles and runs. Only problem is that it doesn't show anything. Reason for that is because the size of your temporary surface is unkown.
    In the init procedure you should also define the size of the surface.
    like so
    [pascal]
    MapSurface.SetSize(256,256);
    [/pascal]

    Hope that helps

  6. #6

    Using multiple surfaces

    Oh shoot, you've beaten me to it Crisp

  7. #7

    Using multiple surfaces

    As far as i know, and asked this same question here before, there is a bug in hw accelerated undelphix_v6. It only works fully with disabling hw acceleration. I still don't know if the maker has found a way around this...

  8. #8

    Using multiple surfaces

    Thanks for your answers. Both were very helpful and both brought up new questions .

    First off, the whole thing works now. The SetSize-Method did the job and not it draws my playfield in all its glory :roll:

    Now the new questions. First, i am going to get a bit more specific about what I want to do. The plan is to program a nice little turn based strategy game. The extra surface i mentioned is used to draw the playfield including terrain, units, buildings and so on. The playfield can be scrolled and my routine draws only the stuff that can actualy be seen by the player. Later, I want to embed the playfield into an interface. To make the playfield independent from the interface i thought it would be a good idea to place it on a seperate surface which i could place later wherever i would like to.
    So would it be better not to use a seperate surface for this but draw everything on directly on the DXDraw.Surface instead? Does the usage of multiple surfaces slow down the drawing process considerably? And for the second question, is there anything wrong with the shorter Draw-Method i used or is it just less flexible?

    About your explanation crisp, it was very clear and i had no problems understanding it
    By the way, thanks a lot traveler for writing these great tutorials. They have really been a great help.

  9. #9

    Using multiple surfaces

    The only problem I see is that it would require more memory & cpu power than normally because you have to create each surface beforehand. As for using part of a surface multiple times, check out the copyrect function.

    I don't think multiple temporary surfaces slow down the drawing that much. And since you are planning on doing a turn based game, fps isn't going to matter anyway.

    I think the methode of drawing is sort of preference. I doubt one way is faster than the other.

  10. #10

    Using multiple surfaces

    If I understand you correctly it would seem you want to have to surfaces, one for the play window and one for the interface which is overlayed on top of the play surface and then this is all flipped to the user. While this would work and isn't too much of a drain on memory it would mean blitting a very large image (the play surface) over to the screen when it could have been drawn to screen in the first place. Since this will happen every frame I'm pretty sure you will lose a lot of frames just doing this. I'll endeavor to write a test program that demonstrates the framerate differences between the two methods.
    Isometric game development blog http://isoenginedev.blogspot.com/

Page 1 of 3 123 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •