Visit The new RRC2Soft Tutorials ^_-

We made available new tutorials in www.rrc2soft.com. Enjoy!

RPG's PROGRAMMING TUTORIAL:
FILE 1
Graphics: Creation and usage

    Welcome to the new lesson of this tutorial !. Today we'll learn the usage of graphics in our games. We've the tools (320x200x256), so let's start painting! ^_^.
    First we'll learn how to represent a prite in a game. Next how can we edit sprites (before using it in the game) and save them into HDD, and at least how to take the Sprite from HDD to memory.
    I'll write routines in Pascal, but i think that evebody can read them (Pascal is like PseudoCode).

    NOTE: When I'll define techniques, the one who has (STAR) is used in the Freeware game I develop.
 

Before start
A.D.T. Sprite( What's a graphic for my program? )
Editing graphics and file formats
Reading graphics from Hard Disc
Source Code




BEFORE START....

      PCX Format.

    (Thanks to JASM-BMP, PC-Actual Magazine [Antonio Ropero] and PCGPE for docs and routines)
    PCX Format, developed by ZSoft Corporation, is one of the easiest graphic formats and has a good compression ratio.
    Like all graphic formats, has a Header, a Data Zone and a Tail. Header has graphic info (128 bytes), Data has the graphic (obvious ^_^) and Tail has the palette.

    Of Header, we want these items:

    Of Data, we want to know how the graphic is compressed. PCX uses RLE (Run-Length Encoding). Basis of RLE is compress duplicated pixels. I. E. 12-12-12-12 => 4-12 (4 times 12).
    In PCX, compression is...     In the Tail "lives" the type of palette and the palette itself (If is VGA 256 colors). Byte SizeOfPCX-769 must be 12 for have a 256 colors palette in the last 768 bytes. The colors are written in (R*4)(G*4)(B*4) format.
    Explaining better: There're 256 RGB records (RedGreenBlue. 256*3 bytes =768) in the palette, but every RGB element is written multiplicated by 4. So if we want to read a RGB element, we must divide every component by 4.

    Source Code: In G320x200.PAS stays the procedure MostrarPCX320x200 (ShowPCX320x200), where you can see everything implemented. And in URLE.PAS stays the procedures RLE, RLEPCX y RLEOut, that implements compression/decompression with RLE.
    If you want to see the entire PCX header, look at SWAG or PCGPE v1.0 .

A.D.T. Sprite ( WHAT'S A GRAPHIC FOR MY PROGRAM? )

    First, we'll talk about representing sprites/graphics in our programs.
    NOTE: I've put this section here 'cause graphics has almost the same form in memory and in HDD. (And here the structure can be understand better).

    Graphics like pointers and linked lists

    In 320x200x256 mode, one pixel=one byte. So we can imagine a type Sprite that represents one Graphic/Sprite (people, house, scenario):

        Type TSprite = Record
                                    TamX,TamY:Word; (* Width and Height of the Sprite *)
                                    PSprite:Pointer;   (* PSprite^ = Sprite itself *)
                                End;

    ...where TamX and TamY means the Width and Height of the Sprite, and PSprite is a pointer to a memory region sized (TamX*TamY) that holds the Sprite itself. (1 pixel =1 byte) .[I. E.: a ball 4x4 pixels () would be TamX=4, TamY=4, PSprite^= [0,4,4,0, 4,12,4,4, 4,4,4,4, 0,4,4,0] ].
    And a list of graphics will be a linked list with sprites like elements:

        Type PLSprite = ^LSprite;
                LSprite = Record
                                    Sprite:TSprite;
                                    Next:PLSprite;
                                End;

    I think Ultima 7: The Black Gate use this format (looking at its file formats).
    And of course this is optimal only when we're in protected mode or/and in a linear memory O.S. (Unix, W95), 'cause if we try to do this in real mode, sprites bigger than 64K pixels can't be created, and we can only save a few sprites (we've the 640K barrier). One solution is interpret PSprite like a pointer to an EMS bank. Or we can reserve a big zone of XMS memory for all the sprites, and PSprite is a pointer to the start of the sprite in XMS.

    Sprites like arrays, and saved in group (STAR)

    There's other option when all the sprites have the same size:

    Type TSprite = Array [1..TAMX,1..TAMY] Of Byte (* Best: Array [1.. TAMX*TAMY] Of Byte *)

    ...where the sprite itself is in TSprite. [I.E.: a ball 4x4 pixels () with TamX=4 and TamY=4 will be Sprite= [0,4,4,0, 4,12,4,4, 4,4,4,4, 0,4,4,0] ].
    Like before, we can store the graphics like a linked list or a predefined array. And also we can use EMS or XMS if we aren't in protected mode.
    NOTE: XMS is very slow in comparison with EMS. Think on this.

    Paint a sprite into the screen (STAR)

    When we have the sprite stored on memory, we would want ^_^ to paint it. It's very easy to make:

    (On pseudocode. Parameters: (IX,IY) -> coord. where we want to put the sprite; Sprite -> self-explanatory)
    For X=1 to Width_Sprite
        For Y=1 to Height_Sprite
            PutPíxel(IX+X,IY+Y,Sprite[X,Y]) (* Sprite[,] is the sprite itself *)
        EndFor
    EndFor

    NOTE: We can add some things to this put_sprite. One is add transparent checking (there are pixels in the sprite that aren't painted, if we find them don't exe the putpixel code), and the other is border checking (don't paint pixels off of the screen).

EDITING GRAPHICS AND FILE FORMATS

    Well, we know now how to manage graphics in our programs. But before we need to edit them and save them in HDD. This is the section you need for these jobs.

    Graphics in HDD: Making of

    Every game needs graphics (SVGA 800x600 bitmaps or poligons, modified characters in monochrome text mode,...). But there's a question: We're those graphics ?. In HDD, of course ^_^.
    The basic problem is how to edit them, and where (Graphics don't appear from nothing ;)) ).
    If you need a graphic that needs all the screen, the thing is easy: make the graphic in any editor and save it in a format you know how to read (PCX I. E.).
    But things look worse if you want to save a sprite or a picture larger than your graphical mode. Well, there're many solutions:

    File format for sprites with different sizes

    Well, here I'm going to comment a file format for having sprites with different sizes. It's a little dificult, but with the example i think you will understand::

    (Based on DIV Games Studio's FPG File format)
    Header: 3 Bytes of File-Type | 1 Byte of version.
    Individual Graphic, Header:
            1 LongInteger of ID_graphic (* Not needed, only if you need it *)
            1 Word of graphic_width.
            1 Word of graphic_height.
            1 Word of Pointer_to_palette_file (* NOTE 1 *)
            1 LongInteger of nș of bytes used for the graphic (* NOTE 2 *)
    Individual Graphic, Data:
            Graphic_Width*Graphic_Height Bytes(Pixels). (* NOTE 2 *)

    Then, if i want to read the graphic number X, i must read all the graphics before X, reading the field  nș of bytes used and advancing the read pointer consequently.

    Example:  RRC
                    0
               (Graphic 0)
                    0 - 2 - 2 - 0 - 4 - 123 - 123 -123 -123
               (Graphic 1)
                    1 - 1 - 3 - 0 - 3 - 123 - 12 - 39

    I have two graphics. One is (2x2) and the other is (1x3). For read the 2ș graphic, i need to advance 14 bytes from the start of the file, read a Longinteger (is nș of bytes used=>4), advance 4 bytes, and now i'm in the start of the header of the 2ș graphic.

    An improvement is to use a file that contains indexes to every graphic, and access directly to the start of the header of the graphic.
    There're more improvements:

  (Comes from NOTE 1)

We can have a file with palettes, and this word points to the palette that uses this sprite.

  (Comes from NOTE 2)

We can compress every sprite with RLE, so nș of bytes used is not equal to Graphic_Width*Graphic_Height. We use nș of bytes used for advancing in the file and for know the size of the compressed graphic.
BTW, Ultima 7 has a very similar file format (sprites of different size with RLE).

    IMA File Format (STAR)

    In the adjunct game, We write the sprites (20x20 sized) in PCX files. But after this, i save them in a format called IMA. Is very easy, and its format is:

    (160 graphics in a file)
    Graphic, Data: 400 bytes (pixels)

    Sprites aren't compressed and there's no header and tail. And graphics are stored lineally (First 400 bytes => First graphic; Second 400 bytes => Second graphic;...).
    Easy, huh ? ^_^

READING GRAPHICS FROM HARD DISC

    This section is very, very simple. How to read one sprite X? Well...:

  1. If we had the IMA file format, only read 400 bytes starting on byte 400*X.
  2. If we had sprites on PCX's (or another format), decompress image on VGA/Virtual screen/Memory and read graphic X..

  3. (remember that we start reading in the upper-left corner of the sprite. You must read Height lines, and after every line read (Width pixels) you must advance the read pointer 320-Width bytes).
  4. If you use the file with sprites of different sizes, look at that section (File format for sprites with different sizes).
    ... And you use the structures explained in A.D.T. Sprite ( WHAT'S A GRAPHIC FOR MY PROGRAM? ) for the sprite.

SOURCE CODE

    G320x200.PAS holds type Sprite and every PutSprite(PintaCasillas). Type of IMA file format is only File.
    In the game we read an entire IMA (64000 bytes) and data is passed to a XMS handle (our sprites are stored in 64000 XMS chuncks). When we want to read a sprite nș X, we take 400 bytes starting from the byte 400*X of the XMS chunck.
 

    Well, next one will be more CRPG dedicated: Tiles.
    If you have some doubt, our mail is in every part of this site ^_^.

    See you soon !! 1