home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-08-28 | 169.1 KB | 3,558 lines |
- ░░░░░░▄ ░░░▄ ░░▄ ░░░░░░▄ ░░▄ ░░▄ ░░░░▄ ░░░░░░▄
- ░░█▀░░█ ░░░░▄░░█ ░░█▀▀ ░░█ ░░█ ░░█▀▀▀ ░░█▀░░█
- ░░░░░░█ ░░█░░░░█ ░░█ ░░░░░░▄ ░░█ ░░█ ░░█░░░▄ ░░░░░░█
- ░░█▀░░█ ░░█ ░░░█ ░░█ ▀▀▀▀▀▀ ░█ ░█▀ ░░█ ░░█ ░░█▀░░█
- ░░█ ░░█ ░░█ ░░█ ░░░░░░▄ ░░█▀ ░░░░█▀ ░░█ ░░█
- ▀▀ ▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀
-
-
- ░░░░░▄ ░░░░░░▄ ░░░░▄
- ░░█▀░░▄ ░░█▀░░█ ░░█▀░░▄
- ░░█ ░░█ ░░█ ░░█ ░░█ ▀▀
- ░░█ ░░█ ░░█ ░░█ ░░█ ░░▄
- ░░▄ ░░░░░█▀ ░░░░░░█ ░░░░█▀
- ▀▀ ▀▀▀▀▀ ▀▀▀▀▀▀ ▀▀▀▀
-
- (English documentation)
-
- ┌─────────────────────────────────────────────┐
- │ ANIVGA │
- │ a sprite-unit for TurboPascal V6.0 │
- │ by Kai Rohrbacher │
- │ Version 1.1 │
- └─────────────────────────────────────────────┘
-
-
- Purpose : Animation of sprites on a VGA's 320x200x256 mode and
- TurboPascal V6.0
- Author : Kai Rohrbacher
- Germany
- Internet: S_ROHRBACHER@IRAVCL.IRA.UKA.DE
- Bitnet : UKB8@DKAUNI2.BITNET
- FIDO : 2:241/7521.7
- Language: TurboPascal V6.0
- Date : September 1992
-
- ---------------------------------------------------------------------
- Always remember: "I know my English spelling is bad, but if I used my
- own language you probably couldn't read it at all."
- -- Nico de Vries
- ---------------------------------------------------------------------
-
- 0. Table of contents
- ────────────────────
-
- 1. Prélude: Legal Notices
- 2. What is ANIVGA?
- 3. Features and Restrictions of ANIVGA
- 4. "HELLO WORLD" - A First Example
- 5. How ANIVGA works
- 6. Tips, tricks and techniques
- 7. Credits
- 8. ANIVGA Reference Manual
-
-
- 1. Prélude: Legal Notices
- ─────────────────────────
-
- Okay, the boring stuff first...
-
- The author hereby disclaims all warranties relating to this software,
- whether expressed or implied, including without limitation any implied
- warranties of merchantability or fitness for a particular purpose.
- I will not be liable for any special, incidental, consequential, indirect
- or similar damages due to loss of data/damage to hardware or any other
- reason, even if I have been advised of the possibility of such damages.
-
- This programming toolkit is released as "freeware" by the author.
- It is however copyrighted and all rights and ownership are kept with the
- author. You may use it, copy it and give it to everybody as long as no
- modifications are made -- but don't try to sell it (or part of it)!
-
- Nevertheless, all programs you realize with this software package may be
- distributed/sold freely - the only thing I ask you for is to mention the use
- of this toolkit in your program and to send me a copy of your program, al-
- though a small donation would be *much* appreciated, for the reasons told in
- the file README.2ND (which I hope, you have read thoroughly!).
-
-
- 2. What is ANIVGA?
- ──────────────────
-
- ANIVGA is a powerful toolkit for the animation of sprites on any IBM (or com-
- patible) with a VGA card installed.
- It consists of one (big) TurboPascal V6.0-unit to be used by your applications
- and some utilities to simplify its use:
-
- README.1ST - as it tells you: a text file you should read first
- README.2ND - yes, *exactly* what you are thinking right now...
- ANIVGA.DOC - the manual, you are reading it!
- FAQ.TXT - some frequently asked questions
-
- ANIVGA.PAS - the source code of the animation unit
- MAKES.EXE - a spritemaker program (requires a mouse and a Super-VGA-card!)
- GRAB.EXE - a TSR-program to grab sprites from other graphics (req. mouse)
- UNLIB.EXE - a utility to break apart a library of sprites back into
- its individual sprite files
- DUMP_SPR.EXE - a "sprite dumper" which disassembles a (binary) sprite file
- into a (recompilable) ASCII-text
- EXAMPLE?.PAS - a few _simple_ demo programs
- *.COD, *.PAL - some sprites and palettes, which belong to the demo programs
- SVGA256.BGI - a BGI driver, only used for MAKES.EXE
-
- TRANSLAT.EXE - a utility to generate a version of ANIVGA.PAS with English
- comments
- ANIVGA.DIC - dictionary needed for the translation
- *.* - documentation, sources, ...
-
- -> Copy these files into your TurboPascal-directory and compile ANIVGA.PAS to
- implement ANIVGA on your system - that's all.
-
-
- 3. Features and Restrictions of ANIVGA
- ──────────────────────────────────────
-
- Some of ANIVGA's features are:
-
- - flickerfree animation by a "page-flipping" algorithm and using the
- display enable signal
- - sprite movement in any increments you want
- - arbitrary background image for the animation
- - full use of the VGA's 256-color mode
- - several sprite display methods available:
- - sprites can be written normally (covering underlying figures)
- - sprites can be declared to be transparent with regard to the background
- or other sprites pixel by pixel
- - sprites can change their color depending on the underlying background
- image (-> shadow function)
- - display methods can be different for each sprite
- - pixel precise hit-detection routine built in
- - correct clipping of sprites at the screen boundaries
- - up to 32767 different sprites
- - up to 500 sprites may be simultaneously active
- - maximal size of each sprite = 64k
- - maximal size of all loaded sprites only restricted by available memory
- - works with virtual coordinates in the range -16000..+16000
- - thus simple creation of horizontal/vertical "scrolling" games
- - scrolling background image, too
- - several supporting routines to: drawing lines (with built in clipping-
- algorithm), points and graphic-text (incl. clipping), automatic heap
- management for loading of sprites, sprite libraries, background images,
- processor-speed adjustment, palette handling,...
-
- What ANIVGA does _not_ support:
- - EMS or XMS memory (to slow)
- - resolutions other than 320x200x256 (compatibility question)
-
-
- 4. "HELLO WORLD" - A First Example
- ──────────────────────────────────
-
- ANIVGA uses a non-standard 320x200x256 graphic mode, different from the BIOS-
- mode $13, but there should be no problems with all truly compatible VGA cards.
- To see if ANIVGA is compatible with your system and to get a first impression
- of its ease of use, compile the following _simple_ program (you can find it on
- disk as file "EXAMPLE1.PAS"):
-
- (Remember to copy and compile ANIVGA.PAS in your TurboPascal-Unit-directory
- first!)
-
- PROGRAM Example1;
- USES ANIVGA,CRT;
- CONST LoadNumber=42; {why not 42? - A hello to all Douglas Adam fans!}
- SpriteName='FLOWER.COD'; {Path and name of the sprite to load}
- Sprite1=0;
- Sprite2=5;
- ch:CHAR=#0; {sets ch to that value everytime the program starts}
- VAR collide:BOOLEAN;
-
- BEGIN
- IF loadSprite(SpriteName,LoadNumber)=0
- THEN BEGIN
- CloseRoutines;
- WRITELN('Error: '+GetErrorMessage); halt(1)
- END;
-
- InitGraph;
-
- Color:=66;
- BackgroundLine(0,0,XMAX,0); BackgroundLine(XMAX,0,XMAX,YMAX);
- BackgroundLine(XMAX,YMAX,0,YMAX); BackgroundLine(0,YMAX,0,0);
- BackgroundOutTextXY(100,70,'Hello world!');
-
- SpriteN[Sprite1]:=LoadNumber;
- SpriteX[Sprite1]:=0; SpriteY[Sprite1]:=0;
-
- SpriteN[Sprite2]:=LoadNumber;
- SpriteX[Sprite2]:=XMAX SHR 1; SpriteY[Sprite2]:=YMAX SHR 1;
-
- Animate;
- REPEAT
- collide:=Hitdetect(Sprite1,Sprite2);
- if collide THEN BEGIN Sound(1000); Delay(5); NoSound END;
- if KeyPressed
- THEN BEGIN
- WHILE KeyPressed do ch:=UpCase(ReadKey);
- CASE ch OF
- 'I':DEC(SpriteY[0]);
- 'J':DEC(SpriteX[0]);
- 'K':INC(SpriteX[0]);
- 'M':INC(SpriteY[0]);
- 'E':dec(StartVirtualY,10); {change position of whole scene with}
- 'S':dec(StartVirtualX,10); {E,S,D,X}
- 'D':inc(StartVirtualX,10);
- 'X':inc(StartVirtualY,10);
- END;
- IF POS(ch,'IJKMESDX')>0 THEN Animate;
- END;
-
- UNTIL (ch='Q') OR (ch=#27);
-
- CloseRoutines;
- END.
-
- (Don't worry if you do not understand the whole program at once - it should
- only give you a first impression of ANIVGA's capabilities)
- If you run this program (make sure that the sprite file FLOWER.COD can be
- found by the program!) you should see a graphic consisting of two flowers, a
- rectangle showing the screen boundaries and the words "Hello world" near the
- middle of the screen.
- You can move the top left flower by using the keys "I","J","K","M".
- If you hit the other flower with the first one, the program will beep.
- Try out what happens if you move across the two words in the middle:
- obviously, the two leafs of the sprite behave somehow different: the black
- parts of left leaf are "transparent" in that the writing shines through it,
- while the black parts of the right leaf are "covering black".
- But the writing (which is written in the background image) won't be destroyed.
- As soon as you leave them, the words will be alright again.
- Move the sprite to the very left screen boundary - and move it even more to
- the left: you'll get the impression that it moves off the screen until it is
- totally offscreen.
- Hmmmm - how do we get it back? Sure, "K" will do, but press "S" instead: this
- will "pan" the whole screen 10 pixels to the left (think of that as if you
- could control an imaginary camera to slide to the left), "X" pans into the
- other direction (note the restriction of the program to non-scrolling back-
- ground at this point: the big rectangle and the words "Hello world" won't
- move because they are part of the so-called "static" background image).
- ("E" and "X" will behave similarily, but for the y-direction.)
- Now -using the "I","J","K" and "M" keys- bring back your sprite to the 2nd one
- and let them collide. Press "A" a few times to scroll them both offscreen.
- As you'll notice, the program will not stop beeping: it indicates that the two
- sprites collide, even if they are not visible to you!
- Okay, that should be enough for a first impression, so hit "Q" (or ESC) to
- quit the program, if you've finished wondering... :-)
-
- There are a few more EXAMPLE programs included. They share a common thing:
- they are as small and simple as possible, because they shall only show you
- some basic techniques!
-
- Run EXAMPLE2.PAS for a demonstration of "scrolling" background; the program is
- much the same as EXAMPLE1, but uses four different "tiles" to build the back-
- ground image. As before, you can use "I,J,K,M" to move your sprite along, but
- this time, you may scroll the whole scene (incl. the background!) with the
- "E,S,D,X" keys, too ("Q" quits, as before).
-
- EXAMPLE3.PAS shows (an extremely) simple use of the "Display_SHADOW" mode to
- display a graphical object and demonstrates the difference to mode
- "Display_SHADOWEXACT": first, a sprite is used for its own shadow zone, simply
- by redrawing it with a little horizontal and vertical offset, using mode
- "Display_SHADOW".
- Although this is a nice trick with many sprites (you don't have to design
- extra shadow sprites this way), it doesn't always work: note that there is one
- area in the flower which differs from what we would expect as shadow: this is
- because ANIVGA assumes that everything between the left- and rightmost point
- of a sprite belongs to the sprite's interior and will be drawn accordingly.
- To circumvent this, one would have to draw one (or even several) especially
- designed "shadow zone" sprites for the flower, or use Display_SHADOWEXACT
- instead: just press the space bar to toggle to that mode.
- Pressing "P" draws 1000 randomly distributed points so you can better see the
- shadowing effect for single points.
- Finally, "C" copies part of the screen into memory (with GetImage() ) and
- pastes it somewhere else (with PutImage() ) while clipping off at the screen
- boundaries and is merely there to give a short demonstration of how to use
- these routines.
-
- EXAMPLE4.PAS is an example how to use "sprite cycles": there are six images in
- the sprite (library) file HANTEL.LIB which become "glued" together to form one
- sprite cycle.
- App. one hundred copies of this sprite are then animated on the screen with
- maximum animation speed and again, you can scroll the whole screen area with
- the keys "E","S","D","X". When you do, you will note that as more and more of
- the sprites gets scrolled offscreen, the remaining sprites will rotate faster.
- Pressing the space bar will toggle between fastest animation (no time limit)
- and an animation rate of 200ms per frame.
- You can play around with this value to find out an "optimal" time for your PC
- and this program:
-
- very small: program will show the same symptoms as mentioned above (being
- faster for every sprite offscreen)
- .
- .
- .
- very big : program will slow down even when all sprites are onscreen
-
- Somewhere between lies a value where the animation doesn't get slowed down
- when all sprites are onscreen (=max. work for ANIVGA), but stays at the same
- speed for all other cases (=less work for ANIVGA).
-
- EXAMPLE5.PAS and EXAMPLE6.PAS are two programs to demonstrate how you can
- build a background image by using tiles: a 2x2 (8x4 respectively) COD-file
- will be loaded and pasted repetively into the virtual screen.
- EXAMPLE6.PAS also shows how you may tie sprites and text output to an absolute
- screen position in scrolling background modes!
-
- EXAMPLE7.PAS shows you the same old demo image of the former examples, but
- this time using another palette, loaded from disk.
-
- EXAMPLE8.PAS shows you all opening sequences available by the routine
- "FadeIn()". Press a key A..Y (without Q) to view a method, ESC will quit.
-
-
- 5. How ANIVGA works
- ───────────────────
-
- (It would be _impossible_ trying to cope every detail of ANIVGA, but I'm sure
- you will get the basic ideas of ANIVGA very soon.)
-
- As already mentioned, the program uses a "tweaked" VGA-graphic mode: the VGA
- is programmed in a way to give 4 graphic pages at a resolution of 320x200
- pixels in 256 colors numbered 0..3.
- Page 0 and 1 are used for the display, page 2 holds the "normal" background
- image and page 3 can contain so-called "tiles" which can be used to build a
- huge background image in "scrolling" background mode.
- The basic idea of the "page flipping" scheme used is that: do everything (era-
- sing the old graphic page, draw sprites/lines/pixels/text) on a graphic page
- invisible to the user while showing him a completed page on the screen.
- Then, if finished, "flip" the page, thus making the new, completed page
- visible and the old page to the invisible one. Now start creating the next
- image on this new invisible page - and so on.
- "Erasing" the old image means: overdraw it completely with the background
- image stored in page 2 (or 3), so one could write in pseudo code:
-
- ...
- REPEAT
- show page 0 to user;
- fill (invisible) page 1 with contents of page 2;
- draw new sprites and all other stuff on page 1;
- show page 1 to user;
- fill (invisible) page 0 with contents of page 2;
- draw new sprites and all other stuff on page 0;
- UNTIL DOOMSDAY
- ...
-
- You as the programmer doesn't have to think much about this mechanism, the
- routines keep track of the page flipping automatically: the global variable
- "PAGE" always holds the number of the page which is invisible (and thus:
- the page to be drawn on). Therefore, we say that PAGE holds the "actual page"
- number and 1-PAGE is the page visible to the user.
- Most of the procedures and functions of the animation package adjust them-
- selves to the appropriate page; there are only a few situations where you have
- to be aware of this mechanism, mostly when drawing pixels or to create special
- effects.
-
- The whole package is "table driven". That means, the interface to the user
- consists of some tables in which you specify your sprites to be drawn:
- You store into this tables which sprites to draw ("SpriteN[]") and their
- coordinates (in "SpriteX[]" and "SpriteY[]").
- After this, a call of the main routine "Animate()" gives back control to the
- animation routines, which update the graphic screen accordingly:
-
- ...
- REPEAT
- update SpriteN[]-table:
- deactivate sprite i by storing a "0" into SpriteN[i] or
- activate a sprite k by storing k in an unused SpriteN[]-entry or
- let all the other SpriteN[]-entries as they were last cycle
- FOR ALL SpriteN[i]<>0 DO
- IF SpriteN[i] should change its coordinates
- THEN update (SpriteX[i],SpriteY[i]) accordingly
- call Animate() to draw image and display it
- UNTIL end-of-computer-life
- ...
-
- You should notice that there are two kinds of "sprite numbers" which should
- not be mixed up: one is a spriteLOAD number and represents a handle to the
- (physical) sprite data, while the other (normally termed "sprite number") is
- a logical number to address this sprite data.
- In the pseudo code given above, "k" is the spriteLOAD number (it is a number
- given at load time) and the index "i" in SpriteN[i] is the sprite number.
- Note that "k" is a unique value: you can think of it as a NAME of the sprite
- data loaded (e.g. you could name the FLOWER.COD - data as "123" when loading
- it: there can't be another sprite with the same LOAD-number). On the other
- hand, there could be a hundred flowers on the screen: just choose hundred
- different sprite-table entries (=sprite numbers), e.g. SpriteN[100]..
- SpriteN[199] and store "123" in each of them!
- Whenever you are unsure if you (or I) are speaking of a "sprite number" or a
- "spriteLOAD number", remember that:
-
- ■ A sprite number can hold values in the range 0..NMAX and is an index of
- the tables SpriteX[], SpriteY[] and SpriteN[].
- ■ A spriteLOAD number can hold values between 0..LoadMax and is assigned
- as a "name" to the sprites' physical loaded data; a "0" as load number is
- reserved for "inactivate sprite" (in other words, it is the *content* of
- an entry in SpriteN[])
-
- Example: SpriteN[42]:=0
- │ └ spriteLOAD number
- └ sprite number
-
- The world ANIVGA knows is 32000 pixels wide and high, numbered -16000..+16000
- on each axis. Because your graphic screen consists of only 320 by 200 points,
- (ranging from 0..XMAX and 0..YMAX in the x- and y-axis, respectively; (0,0) is
- the upper left corner, (XMAX,YMAX) the lower right one) you can only see a
- small part of this world, but ANIVGA does not distinguish between the visible
- and invisible parts of the world. If, for example, two sprites collide, the
- routine "HitDetect()" will find out, even if this collision occurs offscreen.
- Thus you can think of your graphic display being a "camera" to the real world:
- your actions can take place everythere in this virtual world, but you see only
- the part displayed by your camera; if you wish to see another part of your
- world, you have to move this imaginary camera to that place.
- In ANIVGA, you can do this by changing the values "StartVirtualX" and
- "StartVirtualY" which hold the upper left corner of the visual window. As an
- example, let (StartVirtualX,StartVirtualY) be (1000,500): then on your screen
- you will see the part of the world which ranges from coordinates (1000..1319)
- and (500..699) in X- and Y-directions, respectively.
-
-
- 6. Tips, tricks and techniques
- ──────────────────────────────
-
- There would be a lot of things to say and most of them will be mentioned in
- the following "Reference Manual". Nevertheless, it seems reasonable to repeat
- them in a more concentrated form here, although this happens to make this
- chapter a real topsyturvydom...
-
- a) The ERROR-concept: if an error occurs in one of ANIVGA's routines, the
- global variable ERROR will be set accordingly. This gives you the freedom
- either to check this variable each time you called a routine - or ignore it
- for improved speed.
- As a rule of thumb, you should always check this variable while your pro-
- gram is still in the testing phase - and "comment out" these sections when
- you are through with debugging. (Conditional defines are great for that
- job!)
- Note that there are some routines that do not set ERROR at all (like
- Screen, GetPixel, PageGetPixel, PagePutPixel), either because in some
- special cases, "nice" tricks can be played with "faulty" parameters or
- because of severe speed improvements! For example, if you are going to read
- a 5000 pixel area from the screen with PageGetPixel(), it would be crazy to
- check 5000 times whether the "page" given to read from is valid or not.
-
- b) Pixel-drawing routines: basically spoken, there are three sorts of graphic
- data objects in ANIVGA: sprites, pixels and background images.
- Because of ANIVGA's working scheme, all routines handling pixels (PutPixel,
- PagePutPixel, Line, PutImage,...) must be used in a special form:
- - If you use them to "draw" into the background page, this can only be done
- when using background mode STATIC (because in mode SCROLLING, the back-
- ground is stored in a compressed "tiling" format one can't access
- directly).
- - Drawing into the background page in mode STATIC is fine (that's the main
- advantage of this mode compared with mode SCROLLING), and the best time
- to do it is _before_ calling Animate(), because changes to the background
- image will then be visible with the call to this routine.
- - Drawing "on the monitor screen" will be visible exactly for one animation
- cycle, that is: until the next call to Animate(). For this reason, you
- must do this changes _after_ calling Animate() and at the _visible_ page
- 1-PAGE (not the _actual_ page PAGE itself).
-
- It is not that difficult as it may sound at first glance; for example:
- ...
- REPEAT
- read_user_inputs; compute_necessary_actions;
- do_all_changes_to_the_background_image;
- do_all_changes_to_the_sprites;
- Animate();
- do_all_changes_to_the_visible_screen;{e.g.: Line(0,0,XMAX,YMAX,1-PAGE)}
- UNTIL user_wants_to_end_application
- ...
-
- This way, after having called Animate(), the changes to the background
- (and your sprites) will be visible (because Animate() has generated an
- appropriate picture) and your changes to this image with the pixel-
- drawing routines will be visible "at once".
- That image will then stay visible until the next call to Animate().
- (Simply spoken, you let Animate() generate and display a picture and then
- do some changes to the picture while it is diplayed)
- - Because of unavoidable memory restrictions, ANIVGA can't store pixels
- drawn offscreen: if ANIVGA sees that points/lines lie outside the visible
- screen, it just does nothing at all; in other words, you can't draw a
- line outside the screen and "scroll it in" five minutes later! (You would
- have to define the line as a sprite instead, because sprites are the only
- objects stored independently).
-
- c) Coordinates: Throughout all routines, ANIVGA works with _virtual_ coordi-
- nates (that is values in the range xε[-16000..+16000], yε[-16000..+16000]),
- but sometimes you will have to address _absolute_ coordinates (in the range
- xε[0..XMAX], yε[0..YMAX]), so you have to transform virtual coordinates
- into absolute coordinates (or vice versa), which is _very_ easy:
-
- virtual coordinates -> absolute coordinates:
- Xabsolute := Xvirtual - StartVirtualX
- Yabsolute := Yvirtual - StartVirtualY
-
- absolute coordinates -> virtual coordinates:
- Xvirtual := Xabsolute + StartVirtualX
- Yvirtual := Yabsolute + StartVirtualY
-
- d) Background / valid pages: Many routines expect a graphic page number as
- parameter. As mentioned under b), BACKGNDPAGE is valid only when you use
- background mode STATIC. Nevertheless, you could draw to this page even when
- you are using background mode SCROLLING without getting an error
- "Err_InvalidPageNumber" (although you are _strongly_ discouraged to do
- so)!
- That's because you can play some tricks on ANIVGA this way, provided that
- you do know _exactly_ what you (and ANIVGA) are doing, but this "feature"
- will probably be cut off in future versions of this program.
- (Note that this doesn't mean that you can't switch between STATIC and
- SCROLLING backgrounds during runtime! - It only says that you can't use
- the two background pages _in parallel_ (=at the same time)!)
-
- e) Display objects at the same abolute screen position:
- Let us assume you want to display a score at the upper right corner of the
- screen; that's not hard when using STATIC background: just define your
- score as a sprite and choose an appropriate coordinate pair.
- In SCROLLING mode, your score would scroll away, too, so you must tie it to
- absolute screen coordinates, as said in c), but there is a simple rule
- which can be derived from the equation
-
- absolute_coordinate := virtual_coordinate - StartVirtual_value
-
- To ensure that the absolute (=screen) coordinate stays the same, you have
- to balance out changes done to the StartVirtual-variables like this: when-
- ever you increase/decrease StartVirtualX|Y by some amount delta, increase/
- decrease your score-coordinates by the same amount delta!
- (This results in: new_coord := virtual_coord±delta - (StartVirtual±delta)
- = virtual_coord - StartVirtual = old_coord as wanted)
-
- f) Displaying scores: another way to display a score without defining it as a
- sprite would be to simply draw it to the screen with the pixeldrawing rou-
- tines or OutTextXY():
- ■ draw it to the visible page (1-PAGE) each time after having called
- ANIMATE()
- ■ draw it to the background page BACKGNDPAGE
- The last method is applicable only in background mode STATIC and you have
- to restore the background image in the used area manually, but has the ad-
- vantage that you must redraw your score only when it really changed (in-
- stead of every animation cycle as with the first method). One way to
- accomplish that would be to use the GetImage() and PutImage() routines:
- ...
- build background image;
- use GetImage() to get a copy of the background area which will be overdrawn
- by the score;
- ...
- main_loop:
- IF new score has to be displayed
- THEN BEGIN
- use PutImage() to restore old background area underneath the score
- use OutTextXY() to write new score into the background image
- END
- ...
-
- g) Speed: It is hard to predict the speed of animations, because that is
- merely determined by the speed of your VGA card, not your computer's CPU
- clock rate! E.g., a program runs faster on my old AT (8MHz) than on a fast
- (25 MHz) 80386 machine - only because of a better VGA card installed in
- the AT!
- Stated otherwise, if you use a computer with "enough" CPU-power, you won't
- have to think much about "should I use STATIC background instead of SCROL-
- LING for improved speed?", because it won't matter much anyway!
- The break even point, where the VGA-card's bottle neck becomes the limiting
- factor depends largely on your application (and your VGA-card, of course),
- but as a rule of thumb, clock speeds faster than 12MHz won't improve your
- program speeds *linearly* any further:
-
- animation ^ ______
- speed │ ___----
- │ /
- │ /
- │/
- ┼─────┬───────────> clock rate
- break-
- even point
-
- Note that your programs will still profit from faster CPU's, but that is
- due to faster computation of all routines not limited by accessing the
- video RAM; even on the fastest clones, the IBM-bus-clock-rate is not faster
- than 10MHz -- and this limits accessing the VGA card: sad, but true...
-
- h) DMA access: Quite a long time, I tried to speed up animation rates by using
- the DMA-chip in parallel to the CPU: while the CPU is running your program,
- the DMA should move around memory.
- Unfortunately, I had to find out that most computers don't like DMA memory-
- to-memory transfers at all and those who do don't work when addresses used
- reference the video RAM area. One of you (TNX Mike!) meant that's due to
- the fact that most VGA cards do not decode the necessary DMA signals.
- [comment: @!%*!@$ ]
-
- i) Speedup things: Naturally, STATIC background is faster than SCROLLING
- backgrounds, but you can speed up SCROLLING backgrounds, too: make sure
- that StartVirtualX always is a multiple of 4 (that is, StartVirtualX
- MOD 4 = 0), because then, ANIVGA can (and will) use the VGA's write mode 1
- which is a lot faster than normal write mode 0.
- Another idea is to shrink NMAX: if you don't need more than 100 sprites
- (say), then change that constant and recompile ANIVGA!
-
- j) GRAB: If GRAB won't pop up, then save the picture to disk (it's wise to do
- that anyway), run a graphic viewer to merely display the picture and
- capture then.
-
-
- 7. Credits
- ──────────
-
- Honour to whom honour is due! I would like to thank some people on this way:
-
- - Ken Pottebaum for his TSR-unit TSRUNIT.ZIP, providing the routines necessary
- to write the Grabsprite-Utility
- - John Bridges for his SVGA256.BGI driver (out of his SuperVGA-driver package
- SVGABGI3.ZIP) used in the sprite maker
- (The above mentioned programs are available at the SIMTEL20-servers)
- - Bernd Klawonn (?) for his principle of using table-driven graphics in the
- first graphics toolkit I ever saw - long, long ago in the "good'ol-AppleII-
- days" (~1985)
-
-
- 8. ANIVGA Reference Manual
- ──────────────────────────
-
- This reference manual lists all routines, variables, constants and a lot of
- informational stuff concerning ANIVGA in alphabetic order.
- Don't get frightened about the amount of informations given; in normal appli-
- cations you will need only a few of them!
- (Start with looking at the example *.PAS files and play around with them
- - you'll learn a whole lot more by first using them as templates than by
- reading manuals!)
-
-
- ABSOLUTE COORDINATES - information
- ──────────────────────────────────
-
- See : coordinates
-
-
- ActualColors - variable
- ───────────────────────
-
- Function : Supplies the actually used palette
-
- Declaration: VAR ActualColors:Palette;
-
- Description: This variable holds the values of the actual graphic colors.
- You can use it to change the palette, but must issue a call to
- SetPalette() to make your changes visible.
- E.g., to make color 5 to "mere green", you would code:
- ActualColors[5].red :=0;
- ActualColors[5].green:=63;
- ActualColors[5].blue :=0;
- SetPalette(ActualColors,TRUE); {or ...,FALSE}
-
- Note : -Whenever you change palette values by using the routine
- SetPalette(), ANIVGA reflects the changes in ActualColors, that
- is, as long as you don't work around ANIVGA's SetPalette()-
- routine by directly tempering with the VGA's palette registers,
- ActualColors always holds the actual palette (so you won't need
- GetPalette() )
-
- See also : Palette, SetPalette, GetPalette
-
-
- Animate - procedure
- ───────────────────
-
- Function : Performs a complete animation cycle
-
- Declaration: PROCEDURE Animate FAR;
-
- Description: A call to Animate() clears the invisible graphic page by copying
- the contents of the background image into the actual drawing
- page (specified by variable PAGE).
- Then all active sprites (SpriteN[i]<>0) in the visible window
- (determined by StartVirtualX and StartVirtualY) are drawn in the
- style and at the coordinates given by the user.
- After that, the routine waits for the display enable signal to
- reprogram the VGA adapter to flip the display pages, making the
- completed image visible and changes PAGE to point to the new,
- invisible graphic page.
- Finally, the procedure looks how much time passed since the last
- animation cycle and if this time is less than that set by
- SetCycleTime(), the program waits accordingly.
-
- Note : This procedure is the kernel routine which has to be called
- everytime when you have set all data for a new animation frame.
-
- See also : PAGE, SetCycleTime, StartVirtualX, StartVirtualY
-
-
- ANIVGAVersion - constant
- ────────────────────────
-
- Function : Holds version number of ANIVGA-unit
-
- Declaration: CONST ANIVGAVersion=11;
-
- Description: Starting with V1.1, all versions of ANIVGA will define this
- constant, holding the version number of the unit.
-
- Note : This constant is new with version 1.1; if for some case you need
- a homogenous scheme for version 1.0, too, then you must add the
- definition "ANIVGAVersion=10" to somewhere in the constant decla-
- ration part in the interface section of ANIVGA V1.0 and recompile
- that unit!
-
- See also : -
-
-
- BackGndPage - constant
- ──────────────────────
-
- Function : Holds the page number of the backround page
-
- Declaration: CONST BACKGNDPAGE=2;
-
- Description: When using background mode STATIC, BackGndPage specifies the page
- number of the background image for the animations to be used.
-
- Note (!) : Use of this constant only makes sense when using background mode
- STATIC!
-
- See also : ScrollPage, Background
-
-
- Background - information
- ────────────────────────
-
- The term "background" specifies a graphic image in front of which all anima-
- tions take place.
- There are two sorts of background in ANIVGA: SCROLLING background and STATIC
- background, which you choose with SetBackgroundMode().
-
- As its name states, a STATIC background cannot be scrolled: it consists of a
- 320x200 pixels picture.
- This background picture is stored in the graphic page numbered BACKGNDPAGE.
- At the very start of every animation cycle, the routine Animate copies that
- picture into the actual drawing page, thus erasing old stuff on that page and
- building the basis for the new image.
- As a normal bitmap picture, it is 320x200=64000 bytes in size. If you use the
- GRAB-Utility or the WritePage()-Routine to save an image, a three byte header
- is put ahead of the information, thus extending the size to 64003 bytes.
-
- The second background sort is called SCROLLING: like ANIVGA's virtual coor-
- dinates, you can define a huge background image and scroll over it.
- Unfortunately, it is impossible to hold a complete background picture in
- memory: you would need 32000*32000=1024000000 bytes RAM (!) to do that.
- Instead, ANIVGA uses a "tiling" mechanism: tiles are small pictures (16x16
- pixels) which can be combined freely to build the background image.
- You can use up to 256 different tiles and "pin" them on an background area of
- up to MaxTiles (=10000) tiles; everything outside of this background area will
- be assigned to tile no. 0 automatically.
- For example, let us assume that you use only scrolling in the y-coordinate
- axis, 16 screens in total: thus, your x-coordinates reach from 0 to 319 and
- your y-coordinates from 0..(16*200-1)=5119, which gives an area of 320*5120
- =1638400 pixels.
- This is equivalent to (320/16)*(5120/16)=20*320=6400 tiles (remember: each
- tile consists of 16x16 pixels!).
- So you would define the scroll range for the background area needed with
- SetBackgroundScrollRange(0,0,319,5119) and start "painting" your background:
- You could design up to 256 different tiles and use them to assemble your
- background image (=those 6400 tiles).
- Most often, only a few are needed, because the background image isn't that
- dramatically different all over the place. For simplicity, let's assume that
- you need only 20 different tiles, numbered 0..19 respectively in the following
- order to build your background image:
-
- (0,0) (319,0)
- ┌────────┬────────┬────────┐ ┌────────┬────────┬────────┐
- │ │ │ │ │ │ │ │
- │ 0 │ 1 │ 2 │ ... │ 13 │ 14 │ 15 │
- │ │ │ │ │ │ │ │
- ├────────┼────────┼────────┤ ├────────┼────────┼────────┤
- . . . . . .
- . . . . . .
- . . . . . .
- ├────────┼────────┼────────┤ ├────────┼────────┼────────┤
- │ │ │ │ │ │ │ │
- │ 0 │ 1 │ 2 │ ... │ 13 │ 14 │ 15 │
- │ │ │ │ │ │ │ │
- └────────┴────────┴────────┘ └────────┴────────┴────────┘
- (0,5119) (319,5119)
-
- Now all you have to do is to tell ANIVGA that layout with the PutTile command:
-
- {assuming SetBackgroundScrollRange(0,0,319,5119) has been set}
- number:=0;
- y:=0; {better: y:=BackY1}
- REPEAT (things would become easier if Pascal would know a STEP-command...)
- x:=0; {better: x:=BackX1}
- REPEAT
- PutTile(x,y,number);
- number:=(number+1) MOD 16;
- inc(x,16);
- UNTIL x>319; {better: x>BackX2}
- inc(y,16);
- UNTIL y>5119; {better: y>BackY2}
-
- That's it! (It is better to use the (global defined) "Back..."-variables, set
- by the former SetBackgroundScrollRange()-call, because ANIVGA has to adjust
- values on multiples of 16, see SetBackgroundScrollRange()/Back?? for more
- details).
-
- So then, why should one use STATIC backgrounds after all when there is such a
- powerful instrument like SCROLLING backgrounds?
- There are two simple answers: speed and simplicity! - First, SCROLLING back-
- grounds take a lot of work to compute, which slows down animations (unless you
- have a fast machine, because then the VGA's memory access time becomes the
- limiting factor). Second, it is easy to do some "tricks" on static back-
- grounds:
- draw a line in the static background page and >zap!< starting with the next
- animation cycle, it will be visible for all times. Stated otherwise, when
- using scrolling background, you cannot use drawings to the background image,
- because it simply doesn't exist explicitly, you are restricted solely to
- "tiles" and "sprites"! (On the other hand, you can play nice tricks on scrol-
- ling background by changing single tiles...)
- So consider carefully what mode you are going to use for your application!
-
- See also : BACKGNDPAGE, BACKGNDADR, WritePage, LoadPage,
- WriteBackgroundPage, LoadBackgroundPage, SetBackgroundMode,
- LoadTile, Tile
-
-
- BackgroundGetPixel - function
- ─────────────────────────────
-
- Function : Reads a background pixel's color
-
- Declaration: FUNCTION BackgroundGetPixel(x,y:INTEGER):BYTE; FAR;
-
- Description: This routine will return the color value of the specified point
- with virtual coordinates (x,y) in the background image.
- If the corresponding absolute coordinates lie outside the screen,
- zero (= black) will be returned.
-
- Note : Use of this routine works only when using background mode STATIC!
- It might look strange to use virtual coordinates then, although
- the background is said to be static (= non-scrollable) and hence
- restricted to absolute coordinates anyway, but it is often con-
- venient to use an uniform notation and it is easy to convert co-
- ordinates accordingly (see "coordinates" for more about that).
-
- See also : coordinates, GetPixel, PageGetPixel
-
-
- BackgroundLine - procedure
- ──────────────────────────
-
- Function : Draws a line on the background page
-
- Declaration: PROCEDURE BackgroundLine(x1,y1,x2,y2:INTEGER); FAR;
-
- Description: To draw a line on the background page (thus alterating the back-
- ground), you can use this procedure. Like the similiar Line()-
- routine, it uses virtual coordinates, too.
- If necessary, the line will be clipped down to its visible part
- (using a special Sutherland-Cohen algorithm).
-
- Note : Use of this routine only makes sense when using background mode
- STATIC!
-
- See also : Line, coordinates
-
-
- BackGroundMode - variable
- ─────────────────────────
-
- Function : Holds the actual choosen background mode
-
- Declaration: VAR BackgroundMode:BYTE;
-
- Description: Using SetBackgroundMode(), you can select one of the possible
- background modes STATIC or SCROLLING. BackGroundMode stores this
- value.
-
- Note (!) : Only read this value, never change it directly!
-
- See also : Background, SetBackgroundMode
-
-
- BackgroundOutTextXY - procedure
- ───────────────────────────────
-
- Function : Writes a textstring to the background page BACKGNDPAGE
-
- Declaration: PROCEDURE BackgroundOutTextXY(x,y:INTEGER; s:STRING); FAR;
-
- Description: This routine is exactly the same like OutTextXY() (see there), but
- it writes the string into the background page (so it will be visi-
- ble permanently).
-
- Note : Use of the routine only makes sense if STATIC is used as
- background mode. With SCROLLING backgrounds, use OutTextXY()
- instead.
-
- See also : GraphtextColor, GraphtextOrientation, GraphtextBackground,
- OutTextXY, background
-
-
- BackgroundPutPixel - procedure
- ──────────────────────────────
-
- Function : Plots a point into the background page
-
- Declaration: PROCEDURE BackgroundPutPixel(x,y:INTEGER; color:BYTE); FAR;
-
- Description: (x,y) specify the virtual coordinates of the point to be drawn in
- color "color". If this point lies onscreen (i.e.: its _absolute_
- coordinates are between (0,0)..(319,199)), it will be drawn on the
- background page BACKGNDPAGE (and become visible starting with the
- next animation cycle).
-
- Note (!) : - Use of this routine makes sense only when using background mode
- STATIC!
- - This routine works with virtual coordinates! - Although this
- seems silly at first glance (because in STATIC mode, background
- coordinates are always restricted to (0,0)..(319,199)), it
- appears to be handy in many situations. If you actually want to
- address points absolute coordinates (a,b), you can call this
- routine with coordinates (a+StartVirtualX,b+StartVirtualY)
- instead.
- - Because of ANIVGA's working scheme, you probably want to call
- this routine _before_ calling Animate(), so that changes of the
- point will be visible as soon as possible.
-
- See also : PutPixel, PagePutPixel, background, coordinates, How ANIVGA works
-
-
- BACKX1, BACKX2, BACKY1, BACKY2 - variables
- ──────────────────────────────────────────
-
- Function : Hold the background image boundaries in background mode SCROLLING
-
- Declaration: BackX1,BackY1,BackX2,BackY2:INTEGER;
-
- Description: When background mode SCROLLING is to be used, you have to define
- a scrolling area (with SetBackgroundScrollRange()). Due to inter-
- nal management restrictions of ANIVGA, the boundaries of this area
- must fall on coordinates which are multiples of 16 ("on a grid
- with mesh 16").
- If the values you supply don't fulfill this restriction, ANIVGA
- adjusts them automatically to do so and stores them to these
- variables for further use.
-
- Note : The only reason these variables are visible to you are that it
- could be necessary for you to notice adjustments ANIVGA did;
- so: only read this values, never change them directly!
- (Look at "background" for an example).
-
- See also : background
-
-
- CloseRoutines - procedure
- ─────────────────────────
-
- Function : Terminates ANIVGA
-
- Declaration: PROCEDURE CloseRoutines; FAR;
-
- Description: Calling this routine switches back from ANIVGA's special graphic
- mode into the graphic or text mode previously set.
-
- Note : This should always be the last call to a routine of ANIVGA in your
- programs.
-
- See also : InitGraph
-
-
- COLLISION-DETECTION, CONCAVE, CONVEX - information
- ──────────────────────────────────────────────────
-
- A graphical figure can be classified by its outline into one of two groups,
- called "concave" or "convex" figures.
- To motivate this mathematical notion >eh, don't get frustrated...<, regard
- your sprite only given by its "outmost" points, which connected together shape
- the figures boundaries.
- The figure is called "convex" :<=> every pair of arbitrarily choosen points
- on this boundary build a line which is totally inside (or at least on the
- boundary of) the figure:
- ┌──────┐ This rectangle is "convex", because whenever you choose two points
- │ │ on its boundaries and connect them, the resulting line lies com-
- └──────┘ pletely inside (or on the boundary) of the rectangle itself.
-
- ┌──────┐ On the other hand, this figure would be "concave", because if you
- └─┐ ┌─┘ choose the top-right and bottom-right corner (say) and connect them,
- ┌─┘ └─┐ then the middle part of the resulting vertical line lies outside the
- └──────┘ figure.
-
- That is (in a very lax form) the _mathematical_ definition of these terms, but
- ANIVGA completely deals with either horizontal or vertical lines, so that an
- extension of these terms can be made:
-
- A sprite is called "horizontal concave" ("vertical concave"), if a horizontal
- (vertical) line connecting two points of the sprite's boundary can be found
- so that parts of this line lies outside the sprite; if the sprite is not hori-
- zontal (vertical concave), it is "horizontal convex" ("vertical convex").
-
- In that sense, the second of the figures above is "vertical concave", but
- "horizontal convex"!
- (Notice that figures which are concave in the pure _mathematical_ sense are
- sometimes treated as convex by this definition, as this cross:)
- ┌─┐ (If you use either a horizontal or vertical "scan line" sweeping
- ┌─┘ └─┐ throughout the cross, there will be never more than one part of
- └─┐ ┌─┘ the "scan line" which belongs to the figure; you can use this
- └─┘ principle as a second definition for horizontal/vertical convex)
-
- This terminology comes in handy when describing some mechanisms of ANIVGA: a
- sprite is drawn LINEwise. For this, every point between the leftmost and right-
- most point of a sprite's line is considered to be an _inner_ point of the
- sprite, thus ANIVGA assumes a horizontal convexity! If your sprite isn't, like
- this one...
- ┌─────┐ ...and the points between the two "legs" of this sprite shall still
- │ ┌─┐ │ be treated as "transparent" (assuming they have been defined with
- │ │ │ │ color "black" (=0)), you must use display mode "Display_NORMAL",
- │ │ │ │ because the "Display_FAST" mode would treat them as belonging to the
- └─┘ └─┘ sprite itself and draw them as "covering" black.
-
- (To state it otherwise: whenever your sprite is (at least) horizontal convex
- and you don't need the feature of transparent parts inside the sprite, you
- can use the "Display_FAST" mode without any loss of accuracy in the sprite
- display)
-
- Tip: the spritemaker program MAKES allows to display a sprite's horizontal
- boundaries, which makes it easier for the beginner to decide about that
- figure's convexity. But whenever you are unsure, you still can use mode
- "Display_NORMAL" for drawing it.
-
- ---
-
- Things get a bit more tough when deciding if two sprites collide or not (which
- is an important task): in difference to many sprite toolkits, ANIVGA doesn't
- use a "mask" approach, which makes sprites big and collision detection slow.
- Instead, ANIVGA uses a sprite's outline to decide whether two sprites collide.
- For that, it computes for every line (column) of the overlap region of the
- sprites' surrounding rectangles, whether the sprites overlap horizontally
- (vertically) and says "collision!" only if there are intersections in both
- directions. In pseudo code:
-
- IF smallest_box_around(sprite1) doesn't intersect smallest_box_around(sprite2)
- THEN no_collision
- ELSE BEGIN
- compute the lines and columns for which the 2 sprite rectangles overlap
- FOR every such line compare -with the help of the sprite boundaries- if
- the corresponding lines overlap
- FOR every such column do the same check
- ONLY_IF there is an intersection in at least one line AND one column
- THEN collision!
- ELSE no_collision
- END
-
- If you think a byte (=8 bits...) about this algorithm, you'll see that it can
- lead to misdetection, in that the algorithm says "collision!", although there
- is none (but it still guarantees that if there _is_ a collision, the alg. will
- detect it) as in the following example:
- ┌─────┐
- └───┐ │
- ┌────────┐ │ │
- │ ┌────┐ │ │ │
- │ │ ┌─┐│ │ │ │ <─ In this line there is a "horizontal collision" (that is,
- └─┘ │ │└─┘ │ │ the two sprites overlap in their horizontal dimension)
- │ └────┘ │
- └────────┘ ┌─ In this column there is a "vertical collision"
- ^───────┘
-
- To state things without a proof here, such an (unavoidable) misdetection is
- only possible, if at least one of the two sprites is neither horizontal nor
- vertical convex!!!
-
- Even then, it takes special constellations (as the one above) to produce such
- an error, so that in praxis, it is very unlikely for such an error to occur.
-
-
- Color - variable
- ────────────────
-
- Function : Determines the actual drawing color
-
- Declaration: VAR Color:BYTE;
-
- Description: Various drawing routines use this global variable to determine
- which color should be used.
-
- Note : ANIVGA uses the standard color table of the 256-color mode $13.
-
- See also : -
-
-
- ColorTable - type
- ─────────────────
-
- Function : Supply a data type for self-defined "Shadow Tables"
-
- Declaration: TYPE ColorTable=ARRAY[0..255] OF BYTE;
-
- Description: If you want to use a different color look-up-table for your
- sprites in display mode Display_SHADOW or Display_SHADOWEXACT
- than can be achieved with SetShadowTab(), you must build a table
- like this.
- Each entry gives the color which should be used to replace the
- original color with that index, i.e.: if c is of type ColorTable
- and c[5]=9, this means that every point of your sprite which is to
- be drawn over a pixel with color 5 should replace that pixel with
- color 9.
- You can find an example how to activate such a "home-brew" table
- at "ShadowTab".
-
- Note : -
-
- See also : ShadowTab, SetShadowTab, Display modes, Palette
-
-
- COORDINATES - information
- ─────────────────────────
-
- ANIVGA has to deal with two kinds of coordinates: "virtual" and "absolute" ones.
- An absolute coordinate lies in the range 0..319, 0..199 for the x and y values,
- respectively. It names a unique point on your graphic screen.
- However, ANIVGA doesn't restrict animations to take place on the visible
- graphic screen: its routines deal with coordinates in the range -16000..+16000
- in each direction, called "virtual coordinates".
- The picture you view while ANIVGA's routines are running is a window of that
- virtual screen, 320 points wide and 200 points high.
- Naturally, the graphic hardware only knows absolute coordinates and thus,
- ANIVGA has to transform virtual in absolute coordinates. It does this with the
- help of the two variables StartVirtualX and StartVirtualY which together speci-
- fy the starting point of the upper left corner of your actual screen window;
- e.g. if (StartVirtualX,StartVirtualY) was (1000,2000) then you would look at
- the part of ANIVGA's world which consists of the 320x200 region with the coor-
- dinates xε(1000..1319) and yε(2000..2199).
- Note that there is one severe restriction, though: because it is absolutely
- impossible to hold a complete "virtual" screen bitmap for ANIVGA's world in
- memory (it would need app. 1GB RAM!), all drawing commands only take place on
- the visible screen.
- This means that you can't draw lines, points or any other objects which are
- _not_ sprites outside the visible window that become visible, when you scroll
- your window over to that part of the virtual screen. For example, if you draw
- a point somewhere outside your visible window (say at (-10000,1234) while your
- visible window starts at (500,900)) and pan to that region afterwards (by set-
- ting (StartVirtualX,StartVirtualY)=(-10100,1200) or something like that), you
- won't see that point: it is stored nowhere.
- (The only way to circumvent this is to define the point as a sprite and set its
- coordinates (SpriteX[],SpriteY[]) to (-10000,1234), because sprites are the
- only objects which the system stores!).
-
- More general:
- Because there is _no_ complete virtual screen, all information drawn outside
- the coordinate range visible at the moment will be lost and all information
- read in from these "offscreen" pixel positions will be zero (= black).
- For that reason it may seem strange for some routines that were restricted in
- their use to the "real" (= absolute coordinate) screen region to use virtual
- coordinates inspite (e.g.: GetImage, BackGroundGetPixel,...), but this was done
- intentionally, because it leaves room for further improvements: if it should be
- possible some day to store a complete virtual screen image, there will be no
- changes necessary in ANIVGA's syntax.
- Meanwhile, it is simple to transform absolute and virtual coordinates into each
- other whenever necessary, using the following equivalence:
-
- virtual X-coordinates - StartVirtualX = absolute X-coordinates
- virtual Y-coordinates - StartVirtualY = absolute Y-coordinates
-
- As a result: virtual coordinates lie in the range -16000..+16000, the start of
- the visible part is defined in StartVirtualX and StartVirtualY and only sprites
- can be "scrolled in" into the visible screen, while all other objects are
- "lost".
-
-
- DefaultColors - constant
- ────────────────────────
-
- Function : Supplies the default RGB-colors of mode $13 to the user
-
- Declaration: CONST DefaultColors:Palette=
- (
- (red: 0; green: 0; blue: 0),
- [...stuff deleted...]
- (red: 63; green: 63; blue: 63)
- );
-
- Description: ANIVGA and its accompanying utility programs are based on the
- Bios' default color palette. That ain't necessary, though (and
- you *can* set different palettes), but it makes things a bit
- easier!
- DefaultColors is a listing of these default colors.
-
- Note : Consider the table as *read only*! When you use SetPalette(),
- ANIVGA will not temper this table (thus you can use it to restore
- the original palette values again).
-
- See also : Palette, SetPalette, GetPalette
-
-
- Display modes - information
- ───────────────────────────
-
- ANIVGA is able to display a sprite in several "modes". This describes how the
- sprite's data should be handled when drawing the sprite to the screen. Up to
- now, there are four modes:
- - Display_NORMAL
- - Display_FAST
- - Display_SHADOW
- - Display_SHADOWEXACT
- This mode is linked to a sprite's physical data by creation of the sprite with
- the spritemaker program (and defaults to Display_NORMAL), but can be altered
- once the sprite is loaded into memory with the procedure SetModeByte().
-
- Note that the display mode information is part of the _physical_ sprites (that
- is, the memory image of the bytes loaded at the beginning), not the _logical_
- sprites (the "handles" in the SpriteN-array to this physical data). For that
- reason, a change of the display mode of a sprite with spriteLOAD number 123
- (say) will affect _all_ sprites of type 123 (= all entries in SpriteN[] with
- value 123). This is intended, because the display mode is a piece of informa-
- tion reflecting the sprite's physical structure!
- (For the case that you disagree: of course you are free to load the same sprite
- with a different load number into memory a second time and assign another
- display mode to this copy!)
-
- In mode "Display_NORMAL" you can think of a sprite as a picture with holes at
- the places where its pixels have color 0: when displayed, all the parts of the
- sprite with color<>0 will cover (paint over) the screens original pixels, but
- the pieces with color=0 will act like "window panes": the original contents of
- the screen remain visible there.
- This mode is useful for all kinds of sprites which have such opaque holes in-
- side themselves: cars/planes/houses or other objects with window panes, but
- also all "concave" sprites. Note that black, COVERING parts must be realized
- with a dark color<>0, for example color 16.
-
- "Display_FAST" is a bit (but not that dramtically) faster than the last method,
- because it doesn't know of a special color: all sprite data is treated equally
- and stored to the screen at once. For that, all parts of the sprite are
- covering. (But note that a sprite consists only of the points "inside" and on
- its boundaries: all the points "outside" the sprite doesn't matter).
- You will use this mode whenever you have sprites which meet the following re-
- quirements: they are "convex" and don't have any transparent parts inside them-
- selves.
-
- "Display_SHADOW" is a tribute to the fact that one often needs some kind of
- shadowing to give the impression of an freefloating object or other pseudo
- 3D-effects. In this mode, the sprite's real colors are insignificant, only its
- boundaries and the actual contents of the screen where the sprite shall be
- drawn are important. The color of every sprite point is determined by the color
- of the appropriate screen point. The color of these points are translated by
- the lookup table ShadowTab into darker ones.
- If you want to give a sprite a shadow zone, then you must divide your sprite
- into two ones: one building the sprite itself and a second one to realize only
- that shadow area, and compose them with appropriate coordinates.
-
- "Display_SHADOWEXACT" behaves quite similiar to "Display_SHADOW", but shadowing
- will only take place at the sprite's pixels with color <>0, that is: color 0
- is again used as "transparent", this time even for shadows! To state it other-
- wise: Display_SHADOWEXACT is for displaying shadows what Display_NORMAL is for
- displaying sprites (and Display_SHADOW relates to Display_FAST in that sense):
- exactly for the same reason, Display_SHADOWEXACT is slower than Display_SHADOW!
- Normally, you will use Display_SHADOW when you are using Display_FAST, too: If
- your sprites are "convex" and don't have any transparent parts inside them-
- selves.
- (If you are still not sure about the difference between these two combinations
- a) Display_FAST & Display_SHADOW
- b) Display_NORMAL & Display_SHADOWEXACT
- then EXAMPLE3.PAS is a good place to try out!)
-
- Technically spoken, there are short code areas in ANIVGA's routines reserved in
- which the right piece of code to transfer/interpret the sprite's data become
- copied, when not already there. For optimal performance it is wise to group the
- entries in SpriteN[] such that adjacent sprite entries share the same display
- method.
-
- See also : convex, concave
-
-
- DUMP_SPR - utility
- ──────────────────
-
- (This is surely a tool for all those hackers among us...)
- If you want to take a closer look at a sprite's data, you don't have to fiddle
- around with DEBUG or the like, just use this sprite dumper: it takes a (binary)
- sprite file (*.COD or *.LIB) and disassembles it into readable ASCII-text.
- You can redirect the output to a file or printer, e.g.:
-
- DUMP_SPR mysprite.cod >mysprite.txt
-
- would dump the sprite file "mysprite.cod" to the ASCII-text file "mysprite.txt"
- for further usage.
- Note that DUMP_SPR creates a format which will be understood by assemblers like
- MASM or TASM so that you can reassemble the files to get a binary sprite file
- once again!
- To do so, you would have to enter the following commands (replace MASM by TASM
- if you use Borland's assembler):
- MASM mysprite.TXT; -> gives you mysprite.OBJ
- LINK mysprite.OBJ; -> gives you mysprite.EXE
- EXE2BIN mysprite.EXE mysprite.COD -> gives you mysprite.COD
-
-
- ERROR - variable
- ────────────────
-
- Function : Holds the code of the last error which occured
-
- Declaration: VAR ERROR:BYTE
-
- Description: If an error occurs while executing one of its routines, ANIVGA
- terminates that routine and sets ERROR accordingly to reflect that
- error.
- You can use GetErrorMessage() anytime to get more information,
- which error occured.
- It is your responsibility to check if such an error occured and
- react in an appropriate way.
- For the possible values and their descriptions returned by
- GetErrorMessage, see there.
-
- Note (!) : - After processing an error, you have to reset the variable back
- to Err_None yourself
- - In respect of future extensions, you should treat every value
- <> Err_None as an error
- - The most frequented routine Animate() doesn't produce any
- errors, neither do several other procedures. As a basic rule,
- all routines which have to do with file I/O have to be checked.
- - ERROR is initialized with Err_None
-
- See also : GetErrorMessage, InitRoutines
-
-
- FadeIn - procedure
- ──────────────────
-
- Function : Fade in a graphic page onto the actually visible page.
-
- Declaration: PROCEDURE FadeIn(pa,ti,style:WORD); FAR;
-
- Description: If you need an interesting opening sequence for your program, then
- FadeIn() is what you need: there are a lot of different routines
- available to copy one image to the actually displayed graphic page
- (1-PAGE): supply the page which shall be displayed "pa" (most
- often, this will be BACKGNDPAGE), "ti" is the time (in millise-
- conds) the fade should last (approximately), "style" defines the
- algorithm to be used and must be one of:
- Fade_Squares,
- Fade_Circles,
- Fade_Moiree1 .. Fade_Moiree14,
- Fade_SweepInFromTop, Fade_SweepInFromBottom,
- Fade_SweepInFromLeft, Fade_SweepInFromRight,
- Fade_ScrollInFromTop, Fade_ScrollInFromBottom,
- Fade_ScrollInFromLeft, Fade_ScrollInFromRight
-
- Note : - The easiest way to use this routine is the following:
- a) initialize the graphic mode via InitGraph(),
- b) load the background page BACKGNDPAGE with your normal
- animation background,
- c) (if you want:) fill the visible page 1-PAGE with whatever
- you want (initially, it is completely black)
- d) call FadeIn(BACKGNDPAGE,2000,Fade_???);
- (about 2000..4000 milliseconds are good values)
- e) continue with your normal program
- - Naturally, ANIVGA can't make your PC faster than it is: the
- time value you supply is a _lower bound_!
- - FadeIn() will use the "normal" MSDos-timer values for its
- operation; as this timer has resolution of about 55msec, it
- is quite inaccurate (..for a computer, I mean..), but as we
- are talking about thousands of milliseconds here, that won't
- matter! (Besides that, this timer won't interfere with the
- one used for the animation rate, set by SetCycleTime()!)
-
- See also : -
-
-
- FillBackground - procedure
- ──────────────────────────
-
- Function : Fills the background page with the specified color.
-
- Declaration: PROCEDURE FillBackground(color:BYTE); FAR;
-
- Description: The given value is written into the whole graphic page BACKGNDPAGE
- and thus defines the picture before all animations take place to
- have one color.
-
- Note : Use of this routine only makes sense when using background mode
- STATIC!
-
- See also : Background, BACKGNDPAGE, BACKGNDADR, GetBackgroundFromPage,
- LoadBackgroundPage
-
-
- FillPage - procedure
- ────────────────────
-
- Function : Fills a graphic page completely with a given color
-
- Declaration: PROCEDURE FillPage(pa,color:Byte); FAR;
-
- Description: If you want to paint a complete page uniformly with one color,
- then this will be the fastest method to do it: specify the graphic
- page (0,1 or BACKGNDPAGE (=2)) in "pa" and the color to be used in
- "color".
-
- Note : - Although possible, you are strongly discouraged to use this pro-
- cedure in background mode SCROLLING (i.e.: pa=SCROLLPAGE (=3) as
- page number), because the background is treated completely dif-
- ferent!
- - Remember also that changes to one of the drawing pages (0 or 1)
- have to be applied _after_ calling Animate and will be visible
- for exactly one animation cycle, whereas changes to the back-
- ground page remain permanent (and are best done _before_ calling
- Animate, although that's not peremptory).
- - This routine is great to produce "flashing" screens: apply it to
- 1-PAGE (the visible page).
- - Possible ERROR-values returned are Err_InvalidPageNumber
-
- See also : background, How ANIVGA works, LoadPage, LoadBackgroundPage,
- GetBackgroundFromPage
-
-
- FontOrient, FontHeight, FontWidth - type/constants
- ──────────────────────────────────────────────────
-
- Function : Supply some additional data about the internal font
-
- Declaration: TYPE FontOrient=(horizontal,vertical);
- CONST FontHeight=6;
- FontWidth=6;
-
- Description: The internal font used for displaying graphic text (OutTextXY(),
- BackgroundOutTextXY()) can be displayed either horizontally or
- vertically; use of the TYPE FontOrient simplifies that.
- To compute the width/height of a text, the constants FontHeight
- and FontWidth can be used, which specify the size of one letter.
-
- Note : -
-
- See also : OutTextXY, BackgroundOutTextXY
-
-
- FreeImageMem - procedure
- ────────────────────────
-
- Function : Releases the memory allocated by a GetImage()-call
-
- Declaration: PROCEDURE FreeImageMem(p:POINTER); FAR;
-
- Description: If you use GetImage(), ANIVGA allocates the memory needed and
- returns a pointer to that area, which you can use with PutImage()
- as often as you desire. If you don't need that clipped image any
- longer, you should release its memory so that it can be used by
- other routines again. To do that, just call FreeImageMem() with
- the pointer GetImage() returned to you.
-
- Note : It is this reason -releasing memory- why you shouldn't make an
- "anonymous" GetImage() / PutImage() combination like
- PutImage(x,y,GetImage(x1,y1,x2,y2,1-PAGE),1-PAGE): you don't get
- a handle which could be used to free the occupied memory!
- Of course, you could use "Mark()" and "Release()", but a simple
- additional pointer variable ("p") is better style:
- p:=GetImage(x1,y1,x2,y2,1-PAGE);
- PutImage(x,y,p,1-PAGE);
- FreeImageMem(p)
-
- See also : GetImage, PutImage
-
-
- GetBackgroundFromPage - procedure
- ─────────────────────────────────
-
- Function : Take over one of the drawing pages as background image
-
- Declaration: PROCEDURE GetBackgroundFromPage(pa:Byte); FAR;
-
- Description: Specify the graphic page (0 or 1) from which the image should be
- "captured" and the routine will copy its contents into the back-
- ground page BACKGNDPAGE (=2) as new background image.
-
- Note : - Use of the routine only makes sense if STATIC is used as
- background mode.
- - Possible ERROR-values returned are Err_InvalidPageNumber
-
- See also : LoadBackgroundPage
-
-
- GetErrorMessage - function
- ──────────────────────────
-
- Function : Returns a description of the last error occured
-
- Declaration: FUNCTION GetErrorMessage:STRING; FAR;
-
- Description: Although you can use the ERROR variable directly to evaluate any
- error and inform the user about it, it is often more comfortable
- to let ANIVGA do that: GetErrorMessage will give you a string
- describing the last error which occured in words.
- The possible string contents and the corresponding ERROR values
- are:
-
- Err_None: 'No Error'
- No error occured during the routine; this is the variable's
- initial value
-
- Err_NotEnoughMemory: 'Not enough memory available on heap'
- The program couldn't load sprites or other data to the heap
-
- Err_FileIO: 'I/O-error with file'
- There was an error reading the file; either the file doesn't
- exist at the path given or it is damaged
-
- Err_InvalidSpriteNumber: 'Invalid sprite number used'
- This error occurs if you try to load a sprite with a sprite
- loadnumber not in the valid range 1..LoadMAX
-
- Err_NoSprite: 'No (or corrupted) sprite file'
- While attempting to interpret the data just read in, ANIVGA
- found the data not to be in the expected format; either because
- you used a wrong data file or it is damaged
-
- Err_InvalidPageNumber: 'Invalid page number used'
- There are four graphic pages, numbered 0..3. Page 0 & 1 are
- used for the animation itself, page 2 ("BACKGNDPAGE") holds the
- static background image and page 3 ("SCROLLPAGE") is reserved
- for the scrollable background information
-
- Err_NoVGA: 'No VGA-card found'
- The animation package needs a VGA (or compatible) graphic card
- but couldn't find one
-
- Err_NoPicture: 'No (or corrupted) picture file'
- The background picture file ANIVGA should load has not the ex-
- pected size/format or a DOS-error occured while attempting to
- access the data
-
- Err_InvalidPercentage: 'Percentage value must be 0..100'
- If you set the colortable for the shadowing effects of sprite
- display mode Display_SHADOW or Display_SHADOWEXACT, you must use
- a percentage value giving the remaining brightness of the colors
- in the shadow areas, which must be in the range 0..100%, of
- course
-
- Err_NoTile: 'No (or corrupted) tile/sprite file'
- There was an error loading the specified sprite file(s) and
- interpreting them as background tiles. Most often this occurs
- because the sprite doesn't meet the requirement to be a multiple
- of 16 points in its x- and y-directions!
-
- Err_InvalidTileNumber: 'Invalid tile number used'
- There may be only 256 background tiles, numbered 0..255
-
- Err_InvalidCoordinates: 'Invalid coordinates used'
- The virtual background coordinates you use must lie in the range
- (BackX1,BackY1)..(BackX2,BackY2), which has been specified with
- SetBackgroundScrollRange()
-
- Err_BackgroundToBig: 'Background to big for tile-buffer'
- ANIVGA's tile buffer can hold no more than MaxTiles (=10000)
- tiles, that is an area of 10000*16*16 pixels². Check the area
- you specified in your SetBackgroundScrollRange()-call!
-
- Err_InvalidMode: 'Only STATIC or SCROLLING allowed here'
- The only background modes ANIVGA knows are STATIC and SCROLLING
-
- Err_InvalidSpriteLoadNumber: 'Invalid spriteload number used'
- spriteLOADNumbers must lie in the range 0..LoadMAX; when you
- get this error, you probably confounded a spriteLOADnumber with
- a spritenumber
-
- Err_NoPalette: 'No (or corrupted) palette file'
- You tried to load a palette file which didn't meet the require-
- ments: a palette file must be of size 3..768 bytes and a
- multiple of 3
-
- Err_PaletteWontFit: 'Attempt to write beyond palette end'
- While attempting to read in and store the palette file into the
- actual color table, ANIVGA noticed that it would have to write
- beyond the end of that table; decrease your "number" parameter!
-
- Err_InvalidFade: 'Invalid fade style used'
- You tried to use a fade style not supported by the unit: look
- at routine "FadeIn()" for allowed styles.
-
- (else): 'Unknown error'
- If ERROR has none of the above values, this string will be
- returned; this should never happen, though.
-
- Note : Calling GetErrorMessage won't set back the ERROR variable either;
- you must do that explicitly!
-
- See also : ERROR
-
-
- GetImage - function
- ───────────────────
-
- Function : Makes a copy of the specified screen region
-
- Declaration: FUNCTION GetImage(x1,y1,x2,y2:INTEGER;pa:BYTE):POINTER; FAR;
-
- Description: - This function works much the same as its equivalent in Turbo-
- Pascal: (x1,y1) and (x2,y2) define the upper left and lower right
- corners of the screen part to save, but now these coordinates are
- _virtual coordinates_, the routine reserves the memory needed to
- hold the copy itself and you can specify the graphic page, from
- which the image is to be taken (pa=0,1 or BACKGNDPAGE (=2) ).
- - As result you get a pointer to the start of the saved image,
- which can be used with PutImage().
- - If there is not enough memory available or the specified part of
- the screen lies completely outside the visible screen, NIL is
- returned.
- - Besides that, there are 5 global variables which are set accor-
- dingly:
- was_cut:BOOLEAN = TRUE/FALSE, if the image had to be _partially_
- clipped (if the specified image is totally offscreen,
- was_cut stays at FALSE!)
- left_cut, right_cut, top_cut, bottom_cut:WORD hold the size how
- much had to be clipped off at the boundaries; these
- values are only set when was_cut=TRUE
- (If you wonder about this odd definitions: GetImage was intended
- to work only with the visible screen (that is: with _absolute_
- coordinates): together with its counterpart PutImage(), you can
- copy a part of the screen to another part or page. In that case,
- you do not have to fiddle around with clipping: just issue a
- GetImage() and use PutImage() to paste this block elsewhere.
- But there may be some applications, when you cut out part of
- the screen and think you got the complete graphic figure you
- wanted, although (because of the use of virtual coordinates and
- your figure being partially offscreen) you got only part of it.
- Checking "was_cut" informs you about such a partial clipping.
- If your figure is completely offscreen, that is a special case:
- it depends on your application whether this should be treated
- as being okay or not; if you need special treatment (as with
- partial clipping), you still can check for this with something
- like:
- ...
- image_ptr:=GetImage(x1,y1,x2,y2,1-PAGE); {1-PAGE=visible page!}
- IF ERROR<>Err_None
- THEN ... {probably not enough memory}
- ELSE IF (was_cut) OR (image_ptr=NIL)
- THEN ... {partial or total clipping occured}
- ELSE ... {no clipping at all}
- )
- - possible ERROR-values returned are: Err_NotEnoughMemory and
- Err_InvalidPageNumber
-
- Note : - As already mentioned, GetImage() only works on screen regions in
- the _absolute_ coordinate range 0..319, 0..199, but expects
- _virtual_ coordinates!
- - To release the memory allocated by a GetImage() call, you must
- use FreeImageMem(); TurboPascal's "Dispose()" won't work.
-
- See also : PutImage, FreeImageMem, coordinates
-
-
- GetModeByte - function
- ──────────────────────
-
- Function : Returns the actual display method set for a sprite
-
- Declaration: FUNCTION GetModeByte(Sp:WORD):BYTE; FAR;
-
- Description: "Sp" specifies the spriteLOADnumber of the sprite from which the
- user wants to know the display mode. The function will return one
- of the valid modes Display_NORMAL, Display_FAST, Display_SHADOW
- or Display_SHADOWEXACT.
-
- Note : - Again, spriteLOADnumbers are used!
- - If the LOADnumber given doesn't exist (because no sprite has
- been loaded with that number), the routine will return
- Display_UNKNOWN instead.
-
- See also : Display modes, SetModeByte
-
-
- GetPalette - procedure
- ──────────────────────
-
- Function : Reads out the actually set color palette directly from the VGA
-
- Declaration: PROCEDURE GetPalette(VAR pal:Palette); FAR;
-
- Description: "pal" specifies the variable in which to store the actual palette.
-
- Note (!) : - This procedure has been added for completeness, merely: As long
- as you make all palette changes by using SetPalette(), you can
- use the variable "ActualColors[]" instead!
- - You must be in graphic mode already or you will get rubbish!
- To state in otherwise: call this routine _after_ having called
- InitGraph() and _before_ calling CloseRoutines()!
-
- See also : SetPalette, Palette, ActualColors
-
-
- GetPixel - function
- ───────────────────
-
- Function : Reads a pixel's color
-
- Declaration: FUNCTION GetPixel(x,y:INTEGER):BYTE; FAR;
-
- Description: Returns the color value of the specified pixel with the virtual
- coordinates (x,y) on graphic page PAGE. If (x,y) lies offscreen
- (to be precise: the computed absolute coordinates lie offscreen),
- then zero (= black) is returned.
-
- Note : Be aware that PAGE is the invisible page, not the one you are
- looking at!
-
- See also : coordinates, PAGE, PageGetPixel, PutPixel
-
-
- GRAB - utility
- ──────────────
-
- GRAB allows you to "steal" graphics from other applications and convert them
- into sprite files (*.COD) or background images (*.PIC) for use with ANIVGA.
- This program is a terminate-and-stay-resident (TSR) utility that has to be run
- before starting those applications from which you want to capture graphic
- images.
- It requires a mouse to be installed and a VGA card - note that an EGA won't do!
- Pressing the hotkey CTRL-ALT-G will popup a frame which you can move and resize
- to select the part of the graphic sreen you want to save (if you are not in a
- graphic mode or in a graphic mode unknown to GRAB you'll here a beep instead).
- Note that if you are in a "MSDos critical" situation, GRAB can't pop up.
- Use the mouse to move the box, hold down the left mouse button and drag the
- mouse to resize the box (in "sprite mode" only). The space bar will toggle
- between "sprite mode" and "background mode", pressing the right button will
- store the framed graphic to disk (either as sprite or background image, what-
- ever program mode you are actually in).
- Press ESC (or both mouse buttons simultaneously) anytime to escape from GRAB
- back to your application.
- By default, GRAB starts in sprite capture mode, thus generating sprite files
- (starting with the file name GRAB_000.COD with increasing numbers for the next
- sprites). To get a background image, toggle into screen capture mode by pres-
- sing the space bar (a second press will switch back to sprite capture mode
- again), select the screen region wanted and press the right mouse button to
- get that part of the screen in the file GRAB_000.PIC (or whatever number is
- actual then).
- In both modes, GRAB also dumps the actually set palette to disk, having the
- same number as the COD/PIC file, but with the ending ".PAL" and a (P)icture
- or (S)prite replacing the underscore, e.g. "GRABS000.PAL" for the first
- sprite saved.
- Naturally, you can't resize your frame in the screen capture mode: it stays at
- its initial size of 320x200 points.
- Note that there is the a restriction for a sprite's size: a sprite may be
- 152x152 points in max., if you need bigger sprites then just save the sprite
- as a PIC file and convert it afterwards, using MAKES.
-
- There is only one possible command line parameter when installing GRAB:
- "BIOS": Supplying "BIOS" tells GRAB to use the video bios interrupt INT10h to
- access all video data. This should work on almost every VGA, but is extremely
- slow.
- Otherwise, GRAB defaults to its internal, fast access routines. Note that some
- applications directly reprogram the VGA hardware so that GRAB must fail on
- them (both in default and BIOS mode)!
-
- Notes :
- o It may happen that you can't popup GRAB in some applications; if you have
- some commercial screen capture utility, you can use that (most often, they
- are more "radical" in their behaviour, using undocumented Dos-funtions and
- the like).
- Then, use an appropriate viewer program and capture the graphic from their
- display!
- (Sorry, I know there are much situations where GRAB _should_ popup, but
- does not - I'm not content with that, either, but I didn't write the TSR-
- unit, but only use it; _if_ I should find the time, I'll write a more
- suitable TSR-unit on my own)
- o Especially if you save a screen as a PIC file, it will take quite a long
- time until GRAB finishes its operation - be patient!
-
- See also : MAKES, Palette
-
-
- GraphTextBackground, GraphTextColor, GraphTextOrientation - variables
- ─────────────────────────────────────────────────────────────────────
-
- Function : Determine how the OutTextXY()-procedures work
-
- Declaration: TYPE FontChar=ARRAY[0..5] OF BYTE;
- Font=ARRAY[0..255] OF Fontchar;
- FontOrient=(horizontal,vertical);
- CONST GraphTextOrientation:FontOrient=horizontal;
- GraphTextColor:BYTE=white;
- GraphTextBackground:BYTE=white;
- FontHeight=6;
- FontWidth=6;
-
- Description: Whenever text is to be written to the graphic screen, ANIVGA
- consults some global variables. GraphTextColor is simply the color
- in which the text should be drawn, GraphTextBackground specifies
- the color for the pixels in between the letters with one special
- value: if GraphTextBackground=GraphTextcolor, then only the pixels
- belonging to the letters will be drawn with all others remaining
- unchanged.
- Finally, GraphTextOrientation tells ANIVGA in which direction the
- text should be written with two values being possible: HORIZONTAL
- (default) for left-to-right text and VERTICAL for top-to-bottom
- style text.
-
- Note : Default color for the text is "white/white" = "white and don't
- change pixel values between letters".
-
- See also : OutTextXY, BackgroundOutTextXY
-
-
- HitDetect - function
- ────────────────────
-
- Function : Checks whether two sprites collide or not
-
- Declaration: FUNCTION Hitdetect(s1,s2:INTEGER):BOOLEAN; FAR;
-
- Description: Call this routine with the sprite numbers of the two sprites to be
- checked for collision; the function will return TRUE/FALSE when
- the sprites collide/do not collide, respectively.
-
- Note (!) : - Collision detection is independent of whether the sprites are
- visible or offscreen: ANIVGA uses the corrdinates of the two
- sprites given (in SpriteX/Y) and internal data to check.
- - For this it is possible to check for collisions _before_ drawing
- an image (with Animate) and thus make necessary sprite updates
- at once!
- - Inactive sprites cannot collide:
- (SpriteN[s1] or SpriteN[s2]=0) -> FALSE
- - A sprite can't collide with itself: (s1=s2 -> FALSE)
-
- See also : Collision-detection
-
-
- InitGraph - procedure
- ─────────────────────
-
- Function : Initialises the VGA card for the use with ANIVGA
-
- Declaration: PROCEDURE InitGraph; FAR;
-
- Description: ANIVGA uses a special graphic mode, which supports 4 graphic pages
- in the resoultion 320x200 pixels and 256 colors. Because this mode
- is not known by the VGA's BIOS, ANIVGA has to reprogram the VGA.
- You should use this command only once to switch into graphic mode.
-
- Note : InitGraph automatically switches to the invisible graphic page
- 1-PAGE.
-
- See also : Screen, CloseRoutines
-
-
- InitRoutines - procedure
- ────────────────────────
-
- Function : Resets all necessary internal variables of ANIVGA to initial values
-
- Declaration: PROCEDURE InitRoutines FAR;
-
- Description: At program start, some variables have to be set and a few system
- checks are necessary.
- Among these are:
- - SpriteN[] and SpriteAd[] become cleared (= set to 0)
- - Page (the actual drwaing page) is set to 0
- - PageAdr is set to the segment address of the drawing page PAGE
- - BackgroundMode is set to STATIC, i.e.: non-scrollable background
- - BackGndAdr is set to the segment address of the background image
- - StartVirtualX/Y are set to (0,0), making the normal screen coor-
- dinates identical to the virtual screen coordinates
- - the old graphic/text mode which was active at program start is
- stored for restoring it at the program end
- - the system is checked if a VGA card is present and the global
- variable ERROR is set accordingly
- - CycleTime is set to 0, which says that there should be no time-
- control mechanism for the animation rate
- - if the machine is not at least an AT, the time mechanism is
- switched off completely
- - COLOR is set to 15 (= white)
-
- The first thing you should do in your programs is to look at the
- ERROR variable: if it was set to something different from Err_None
- (by the implicit, automatical call of InitRoutines) then your pro-
- gram should not proceed further.
-
- Note : - This routine is called automatically at the very beginning of
- every program which uses ANIVGA. For that, there is normally no
- need to call this routine explicitly.
- - Possible ERROR-values returned are: Err_None and Err_NoVGA
- - Note that this is the _only_ routine that definitely sets the
- variable ERROR, either to Err_None or Err_NoVGA. Because it is
- called at the beginning of every program, it is thus assured
- that your application always has a defined value for ERROR!
-
- See also : ERROR
-
-
- Line - procedure
- ────────────────
-
- Function : Draw a line between the two points specified
-
- Declaration: PROCEDURE Line(x1,y1,x2,y2:INTEGER; pa:BYTE); FAR;
-
- Description: Calling this routine will draw a line between the two points
- (x1,y1) and (x2,y2) on graphic page "pa" and in the color COLOR.
- The routine uses virtual coordinates and clips the line down to
- its visible part.
- "pa" must be one of the values 0, 1 or BACKGNDPAGE (=2).
-
- Note : - As with all point-setting procedures of ANIVGA, you have to re-
- member ANIVGA's working scheme: the first thing ANIVGA does when
- Animate becomes executed is to copy the background image to the
- actual drawing page PAGE, erasing everything on that image.
- For this reason, a line drawn on the visible page 1-PAGE will be
- visible exactly one animation cycle.
- - Possible ERROR-values returned are: Err_InvalidPageNumber
-
- See also : PutPixel, BackGroundLine, coordinates
-
-
- LoadBackgroundPage - procedure
- ──────────────────────────────
-
- Function : Loads a background image from disk
-
- Declaration: PROCEDURE LoadBackgroundpage(name:String) FAR;
-
- Description: This routine loads a bitmap image stored in file "name" into the
- graphic page used for the background image (BACKGNDPAGE).
-
- Note (!) : - This routine must be called *after* the graphic mode has been
- initialized (with InitGraph())!
- - You can create such images either with the WritePage()- and
- WriteBackgroundPage()-routines of ANIVGA or the GRAB-Utility.
- - Calling this routine is equivalent to use the routine LoadPage()
- with BACKGNDPAGE as second argument.
- - Possible ERROR-values returned are: Err_FileIO and Err_NoPicture
-
- See also : Background, LoadPage, FillBackground, GetBackgroundFromPage,
- InitGraph
-
-
- LoadMAX - constant
- ──────────────────
-
- Function : Specifies the maximum number of different sprites
-
- Declaration: CONST LoadMAX=1000;
-
- Description: For each physical sprite, ANIVGA uses an internal pointer to its
- data. There are LoadMAX pointers, thus there may be up to LoadMAX
- different spriteLOADnumbers (= different sprites).
-
- Note : Don't mix this constant up with NMAX!
-
- See also : NMAX, SPRITE, SpriteLOADnumbers, Spritenumbers
-
-
- LoadPage - procedure
- ────────────────────
-
- Function : Loads a graphic page from disk
-
- Declaration: PROCEDURE LoadPage(name:STRING; pa:BYTE); FAR;
-
- Description: "name" is the MSDOS-path to the graphic image to load, pa the
- destination page (0,1 or BACKGNDPAGE (=2)).
-
- Note : - The graphic mode must have been initialized (vià InitGraph)
- already!
- - You can generate disk files of graphic pages with the help of
- the WritePage()-routine or with the GRAB-utility program.
- - Don't use this routine to load an image into the SCROLLPAGE,
- i.e.: in background mode SCROLLING!
- - Possible ERROR-values returned are: Err_InvalidPageNumber,
- Err_FileIO and Err_NoPicture
-
- See also : GRAB, WritePage, background, InitGraph
-
-
- LoadPalette - function
- ──────────────────────
-
- Function : Loads a palette into memory
-
- Declaration: FUNCTION LoadPalette(name:String; number:BYTE;
- VAR pal:Palette):WORD;
- Description: "name" is the MSDOS-name of the palette file (*.PAL) to load,
- "number" is the index of the first loaded color in the desti-
- nation array "pal". For example,
- LoadPalette('C:\ANIVGA\TEST.PAL',0,my_pal)
- would load the named palette file into my_pal and the first color
- of this file would be stored in my_pal[0], the second in
- my_pal[1] and so on. (This call - "number" set to 0 - will be
- the form you'll need in 99% of all cases!)
- The routine will read in the complete file and return the number
- of colors read as result.
- All other colors in "pal" before "number" or after the end of the
- specified pal-file will stay untouched!
-
- Note : - As the routine reads in the complete file, you must take care
- not to write beyond the end of "pal"! Especially, if you load
- a complete 256-color palette (size: 3*256=768 bytes), you must
- start at color index 0 (that is: number=0) or you'll get an
- "Err_PaletteWontFit"-Error! Most often however, you will use
- this routine as in the example above.
- - Other possible errors are: Err_FileIO and Err_NoPalette
- - You can call this routine only after having called InitGraph()!
- - You can directly load into ActualColors, that is the sequence:
- Dummy:=LoadPalette(pal_name,0,ActualColors);
- SetPalette(ActualColors);
- is valid!
-
- See also : palettes, SetPalette, GetPalette
-
-
- LoadSprite - function
- ─────────────────────
-
- Function : Loads one (or more) sprites into memory
-
- Declaration: FUNCTION LoadSprite(name:String; number:WORD):WORD; FAR;
-
- Description: "name" is the MSDOS-name of the sprite file to load, which can be
- either a single sprite file (*.COD) or a complete sprite library
- (*.LIB): the function will detect automatically, which format is
- used while loading the data.
- "number" is the spriteLOADnumber, the first loaded sprite will be
- assigned to. If the file contains more than one sprite, they will
- get consecutive LOADnumbers.
- The value returned by the function is the numbers of sprites read
- in (i.e.: 0 means "no sprite read", so you should check ERROR in
- that case).
-
- Note : - Unlike LoadTile(), LoadSprite() loads data into conventional
- memory. For that, you don't have to be in graphic mode to load
- data from disk!
- - Possible ERROR-values returned are: Err_FileIO, Err_NoSprite,
- Err_NotEnoughMemory and Err_InvalidSpriteNumber
-
- See also : sprite format, MAKES
-
-
- LoadTile - function
- ───────────────────
-
- Function : Loads one or more tiles from disk
-
- Declaration: FUNCTION LoadTile(name:STRING; number:BYTE):WORD; FAR;
-
- Description: This routine loads the background tile file "name" into the
- graphic memory area reserved for tiles (the SCROLLPAGE).
- The starting number for the first tile of the file is "number",
- if there are more than one tile in the named file, they will be
- loaded to (with increasing numbers).
- The function returns the number of tiles read in.
-
- Note (!) : - This routine must be called *after* the graphic mode has been
- initialized (with InitGraph)!
- What the function actually does is reading in a sprite and con-
- verting it into an internal tile format: if the sprite read in
- doesn't have the proper size of a tile (16x16 pixels), you nor-
- mally will get an appropriate error (Err_NoTile), with one (use-
- ful) exception: if the sprite can be "cut" into tiles (that is,
- its width and height are multiples of 16 pixels each), then
- LoadTile() will do so with the following numbering scheme: from
- left to right and from top to bottom.
- For example, a sprite with (width,height)=(3*16,2*16) points
- would be numbered as: (assuming that "number" = 0)
- ┌────────┬────────┬────────┐
- │ │ │ │
- │ 0 │ 1 │ 2 │
- │ │ │ │
- ├────────┼────────┼────────┤
- │ │ │ │
- │ 3 │ 4 │ 5 │
- │ │ │ │
- └────────┴────────┴────────┘
- Besides, LOADTILE can load a sprite library, too (they will be
- loaded in the sequence in which they appear in the library).
- - Possible ERROR-values returned are: Err_NotEnoughMemory,
- Err_FileIO, Err_NoTile and Err_InvalidTileNumber
-
- See also : Background, LOADSPRITE, TILE
-
-
- MAKES - utility
- ───────────────
-
- The design of sprites, background pictures and tiles is much to tedious to be
- carried out manually. For this reason, there are two utility programs to
- simplify that task. The first one is a resident program named "GRAB" to
- capture graphics from other applications and convert them into sprites, the
- second is MAKES, a spritemaker program.
- To use it, you must have a mouse installed and a Super-VGA card.
-
- -> MAKES uses a "tweaked" 640x400x256 graphic mode, only available at Super-
- VGA-cards! If you don't have one (or one which chip-set isn't supported by
- the supplied BGI-driver), you won't be able to run MAKES!
- Let me cite from Jordan Hargrave's docs:
-
- >Card types supported: (SuperVGA drivers)
- >Ahead, ATI, Chips & Tech, Everex, Genoa, Paradise, Oak, Trident (both 8800
- >and 8900), Tseng (both 3000 and 4000 chipsets) and Video7.
- >These drivers will also work on video cards with VESA capability.
- >
- >I have not tested these drivers on all these card types, so I can not
- >guarantee perfect operation with your card. I have tested them extensively
- >on Trident, Tseng and ATI cards, and have had no problems. (Trident 8800
- >cards occasionally have problems, especially older models)
-
- If you can't run MAKES, then please drop me a note specifying which brand of
- VGA card you have and which chip-set it uses!
-
- There are no parameters or such things, just start it!
- The screen is divided in several areas:
- - the so-called "work area" in the upper left region, in which you paint your
- sprite
- - the palette area to the right of it, where you choose colors for painting
- or define new colors
- - the info bar right beneath the work area, which informs you about the
- cursor position and some other actually set data
- - the icon field, supplying 18 different functions: 8 "tools" and 10 pure
- functions
- - 10 function boxes at the very screen bottom, which can also be accessed by
- pressing the appropriate function key (ever seen the Norton Commander?)
-
- (Note that a lot of the icons/function boxes have two functions, where the
- second one can be reached by holding down the shift-key while pressing/
- clicking at the icon - this will be described later on, but you can always
- press F1 in MAKES for a short summary.)
-
-
- Now let's take a small tout through MAKES!
-
- -> I propose that you print out this part of the documentation and then start
- MAKES.EXE for the following description!!!
-
- Huh - where to begin? Okay, look at the work area's boundary: it has small
- marks on it, indicating 8 pixel intervals. Move the mouse cursor somewhere into
- the workarea: right beneath the work area, your PC will display the mouse
- cursor's position and what color is currently set at that point. Now move around
- and convince yourself about the marks' values. Press the left mouse button a
- few times: each time, a white pixel will be drawn at the cursor position,
- because "pixel" is the selected tool and "white" the actually set drawing color.
- Nothing whopping, eh? - Now press "+" a few times: wow! You zoom into the work
- area as much as you wish (well, I limited it to a factor 30, but if _that_ is
- not enough you should consider selling your PC for a seeing-eye dog, anyway!).
- Use "-" to zoom out, down to value 1: for easier pointing, the cursor will
- change to a small crosshair pointer when zooming is at factor 1.
- -> Note that as the screen you look at has resolution 640x400, while ANIVGA's
- has 320x200, zoom=2 (the default value) will give you normal 1:1 aspect
- ratio!
- You don't like monochrome pictures? Ok, then click (with the left mouse button)
- at another color in the palette area: this changes the drawing color to the
- color you clicked at.
- Repeat choosing a color, but this time press the _right_ mouse button: a menu
- will pop up and let you change the RGB-values of that color; this way, you may
- alter the palette for your sprites!
- -> Note that RGB-values reach from 0 to 63. If you want to copy another color's
- values, then just click at this color; e.g. if you want to have color 222
- hold the same color as 111 (for example as a template), then click with the
- _right_ button at color 222 and then with the _left_ button at color 111
- Now choose another drawing tool, let's say lines: click at this icon and move
- back into the work area. Choose a starting point and click at it (release the
- mouse button!): now you started a line: move around the mouse to route your
- line; if you are content with it, then press the left button again. If you
- decide to cancel the line drawing instead, then press the right button instead.
- -> This "philosophy" will be used for all tools: press the left button to
- start/advance/complete an action, press the right button any time to cancel
- what you are doing - so get used to it!
- Now repeat the process of drawing a line, but hold down "shift" while you are
- clicking at the starting point: this tells the object "to be aligned" which
- in the context of lines means that you are drawing a horizontal, vertical or
- diagonal line! In the same way, you can align rectangles to become squares and
- ellipses to circles. Try it! Choose these icons and draw the according objects,
- aligned and not aligned (if you choose the lower rectangle/ellipse icon, your
- objects will be filled out with the actual drawing color).
- -> You may select another color even if you are in midst of drawing an object;
- move out of the work area, click at the color you wish - as soon as you
- move back into the work area, your object will change!
- Let's try the filling tool (the left, bottommost one): it will fill all points
- it can reach from the pixel you clicked at having the same color, e.g. if you
- click at a white pixel, it will color all white pixels neighboured to that
- pixel and so on. Note that as long as you don't press the left button a second
- time, this coloring doesn't rest, that is if you move around the mouse after
- having clicked the first time, MAKES will restart its fill algorithm starting
- at the new pixel your mouse points at! This behaviour is a bit confusing in
- the beginning but comes in very handy when you get used to it.
- -> If you really get stuck - especially on slow machines - then just press the
- right mouse button for two or three seconds to cancel the action and start
- over again.
- The last tool to be mentioned is the copy tool (the icon with the scissors):
- you can span a (dotted) rectangular area which you want to copy the same way
- you would draw a rectangle, but after pressing the mouse button a second time,
- a copy of this area will be visible at your cursor which you can place where-
- ever you want to. (Note that color 0 inside this copy will be treated as trans-
- parent, which makes it easier to overlay objects at the screen!)
-
- These 8 icons (the 4 leftmost in the upper and lower row) make up the available
- _tools_, the resting 10 icons are "function buttons", that is: their linked
- action will take place at once (respectively: after asking you necessary para-
- meters).
- I'll first name them, starting in the upper row at the 5th icon, in clockwise
- order:
- a) change color
- b) rotate work area left
- c) rotate work area right
- d) mirror work area horizontally
- e) go/move to the upper-left
- f) display boundaries
- g) mirror work area vertically
- h) rotate work area down
- i) rotate work area up
- j) blink color
-
- a)
- You can replace pixels of a specific color by another color with this tool:
- the program will ask you for the colors, which you can select by either
- clicking in the palette area or by clicking at pixels in the work area itself.
-
- b), c), h), i)
- Clicking at one of these buttons will move the contents of the work area in
- the according direction, but what "falls out" at one side of the work area
- will show up on the opposite side again. If you hold down "shift" while
- clicking, the image will rotate by one pixel, without shift, it will rotate
- by 1/4 of the actual screen width.
-
- d), g)
- I guess these two mirror options should be quite clear; note that as
- they mirror a small image in the upper left corner to the "far away" right/
- bottom region of the work area, you'll often need a tool to "pull back" the
- graphic contents to the upper left corner: that is exactly the task of the
- e) icon: it will move the graphic contents to the top and left as much as
- possible.
-
- e)
- As mentioned above, this tool will move the work area contents to the left
- (and top), until column 0 (row 0) holds a non-zero colored pixel.
- If you hold down "shift" while clicking at this icon, there is another
- functionality: then, MAKES scrolls back the visible part of the workarea
- back to the upper left region of the picture (0,0), that is: this is a short-
- cut for pressing the left- and up-arrow keys a few times (see below for more
- about this).
-
- f)
- If you want to know/see the boundaries of your sprite, then click at this
- icon: the leftmost and rightmost (upmost & bottommost) pixel of each row
- (column) will blink and a popup window will inform you about the sprite's
- size numerically.
- If you hold down "shift" while clicking this icon, MAKES will also blink all
- transparent areas inside the sprite, which may be useful if you don't know
- whether you must use display mode Display_SHADOW <-> Display_SHADOWEXACT and
- Display_FAST <-> Display_NORMAL; in all other cases you can forget about this
- option.
- -> Note that sprites are always stored as the smallest rectangle which
- surrounds them and starts at the upper left corner (0,0): if you don't have
- special reasons to do otherwise, your sprites should start in the upper left
- corner.
- If for example you realize a sprite consisting of one single point at
- coordinates (a,b), the smallest surrounding box with (0,0) as upper left
- corner would be
- (0,0) (a,0) of size (a+1)*(b+1) pixels (=bytes)!!!
- ┌──────────┐
- │ │
- │ │
- │ │
- └──────────▀ <─ this is your 1 point
- (0,b) (a,b)
- (In addition to that, the right edge of this box will be rounded up so that
- the width of the sprite will be a multiple of 4)
- To determine what areas belong to your sprite and which don't, the program
- assumes color 0 to specify no-sprite-areas and all other colors to be part
- of your sprite (roughly spoken).
-
- j)
- If for some reason you must know of all pixels of a specific color (e.g. to
- distinguish two very similiar colors), you can use this function: the program
- will ask you to select the color, what you can do by either clicking at a
- work area pixel with that color or at a color in the palette area.
-
- Okay, now that we are through with the icons, let's have a look at the keys:
- you already know that "+" and "-" zoom in and out the workarea. But if zoom>1
- then only a part of the complete workarea (320x200 pixels) will be visible!
- To work on the "offscreen" regions, you can scroll the work area by using the
- cursor keys: pressing one of the arrow keys will scroll by 1/4 screen into the
- corresponding direction; if you hold down "shift" while pressing an arrow key,
- it will scroll by one pixel instead. The absolute coordinate value of the
- upper left corner you are looking at will be displayed by the two "offset:"
- messages, e.g. "offset X: 40" means that there are 40 columns (0..39) to the
- left of the visible window of the work area, which you may scroll in by
- pressing the left arrow key. (Consider the work area as a view-finder of an
- imaginary camera which you may slide into each direction).
- A short-cut to return to the work area's origin (0,0) is available, too: press
- shift and click at the "go/move to upper left" icon.
-
- The function keys do what they tell you:
- F1 = a short summary of the functionality not visible at first sight
- F2 = save the work area's contents to disk as a sprite file
- F3 = load a previously saved sprite into the work area; if you press "shift"
- while activating this icon (or Shift-F3), then the work area won't be
- erased before loading the sprite: this way, you may overlay several
- sprites on the screen
- F4 = save the actually set palette to disk. Note that if you are using the
- BIOS' default palette, the program won't store it to disk (as you don't
- need)
- F5 = load a previously saved palette. This function is especially necessary
- when you used GRAB to capture a sprite from an application using a
- different palette. (See below for more about palette handling)
- F6 = save the work area's contents to disk, this time as a background picture
- F7 = load a previously saved background picture; the same notes apply as said
- to loading sprites (F3)
- F8 = clear screen. This will erase the work area and let you start all over
- again. Note that it won't reset the palette to the BIOS' default! If you
- want that, you have to press Shift-F9, too!
- F9 = map the workarea colors onto another palette. This feature asks you for
- a palette, loads that and then uses a minimum square algorithm to exchange
- each's pixel color by the one from the specified palette which comes as
- close as possible to the original color. (See below for more about that)
- Shift-F9 works the same, but maps to the BIOS' default palette instead
- of asking you for a palette file.
- F10= quit the program
-
-
- Note :
- o Palettes:
- Note that if you load/save a sprite or picture file, MAKES won't load/save
- the according palette automatically, you have to do that manually. This has
- been done intentionally, however: never forget that you may design a hundred
- sprites with a hundred different palettes, but when it all comes down to
- display these sprites simultaneously in your programs, only *one* palette may
- be active! For that reason, you must mix all those palettes to the one you are
- going to use.
- Normally, that won't be that dramatic, as 240 free color shades (it is *very*
- wise not to change the first 16 EGA-compatible colors) seem enough to me, but
- perhaps you want to include a formerly designed sprite A, using palette B,
- into a new program where you use palette C! Before you start mixing a new
- palette D for this old and your new sprites together, you should try mapping
- old sprite A's colors to palette C: To accomplish that, load sprite A (using
- F3), then load its old palette B (using F5); now press "map palette to
- palette" (F9) and tell the program to map onto palette C: if the result looks
- good enough, then save sprite A (perhaps using a different name) and use
- palette C for all items in your program, else you have to find a compromise
- between palettes B and C (I'm actually working on a program which will auto-
- matize that job, but for now, you are on your own!).
-
- To state it clear: there is a conceptional difference between EXCHANGING a
- color (using the "change color" icon) and CHANGING a color itself (by altering
- the RGB values of one or multiple colors):
- - exchanging colors doesn't change the palette, it merely uses another color
- of that palette
- - changing palette colors doesn't change the pixels' color number, but the
- color's RGB value
- In other words: if you exchange colors, then you don't have to save the color
- palette again, as it didn't change, but the sprite, because its data changed.
- On the other hand, if you changed palette colors, then you'll have to save the
- palette, but not the sprite, as the pixel data didn't change.
- (If you didn't get that: just always save both and forget about it...)
-
- o Mouse problems:
- I noticed that sometimes, the program hangs when initializing the mouse driver
- (when it calls "INT 33h" with AX=0), what you see in that the starting count-
- down doesn't get below 7. I don't have _any_ idea why this happens and hope
- it won't show up on other systems. Note that this is (at least what I noticed)
- a spurious error: cancel the program, restart it once more and it will work!
- Besides that, when quitting the program, MAKES sometimes reports a senseless
- runtime error - it is a spurious, not reproducable error I couldn't track
- down, either (perhaps TP doesn't like my TSR / QEMM installation, I dunno)!?
-
- o Memory:
- You should have at least 256K free RAM if you start MAKES, or it won't work.
-
- o Sprite size:
- If MAKES tells you that it can't save the workarea as a sprite, because it
- is "to big" - well, then you'll have to shrink your sprite! Sorry, but I
- wanted MAKES to handle CODs and PICs at the same time, but 320x200 pixels
- (the size of a picture) is to much for a COD, as the additional data stored
- along with the sprite would make it larger than 64K! (Cut off a few rows or
- columns until it works.)
- Note also that MAKES has to store sprites with widths being a multiple of 4!
- That is: it doesn't matter, whether the max. used x-coordinate is for example
- 316, 317, 318 or 319, because for all those 4 widths (0..316=317 pixels,
- 0..317=318, 0..318=319, 0..319=320), MAKES would have to store them with
- the "rounded up" width of 320 pixels!
- (In other words: although ANIVGA itself can handle sprites up to 32000 pixels
- in each axis and 64K max. size, MAKES restricts you to sprites of x-size at
- most 320 pixels and y-sizes of at most 200 pixels)
-
- o COD <-> PIC:
- Yes, you read right: MAKES doesn't care whether you are working on a sprite
- or a picture graphic: just paint it and store it into the format you want
- (subject to what I said above concerning the 64K limit)! Oh yes, that way
- you may convert a sprite into a background picture (and vice versa) if you
- have reason to do so!
-
- o Tips:
-
- The best way to design a sprite is to start in midst of a cleared work area.
- If you need more room, rotate your sprite in the appropriate direction.
- If you think you're done, use the rotate boxes again (or the "move to upper-
- left" icon) to align your sprite with the upper left corner. Then click on
- the "display boundaries" box to compare the sprite's size with what you
- expected. To wide (high)? Then there is a pixel with color <> 0 to the right
- (beneath) your sprite! Look at the max. column (row) MAKES told you and kill
- that pixel! (To see it more clearly, just hold down "shift" while clicking
- at the "display boundaries" icon).
-
- If you are unsure whether you can use display mode Display_FAST or need
- Display_NORMAL (same applies for Display_SHADOWEXACT and Display_SHADOW),
- then hold down "shift", click at the "display boundaries" icon and look at
- the picture: if the blinking parts "spread" out of the parts you think your
- sprite should be made of, then you should use Display_NORMAL
- (Display_SHADOWEXACT, respectively), if all the blinking areas are inside your
- sprite, you can (and should) use Display_FAST (Display_SHADOW).
-
- See also : sprite format, GRAB, Display modes
-
-
- MaxTiles - constant
- ───────────────────
-
- Function : Holds the maximum number of tiles to build the background image
-
- Declaration: CONST MaxTiles=10000;
-
- Description: In background mode SCROLLING, you may use up to MaxTiles tiles
- to build your graphic image.
-
- Note : -
-
- See also : Background
-
-
- NextSprite - variables
- ──────────────────────
-
- Function : Holds the "successors" of sprites for sprite cycles
-
- Declaration: VAR NextSprite: ARRAY [0..LoadMAX] OF WORD
-
- Description: To realize a sprite cycle, you must tell ANIVGA which sprites
- should be drawn one after another. It is this information
- NextSprite holds! For example, let us assume that you wanted to
- make the sprite(loadnumber)s 43, 177 and 111 a sprite cycle, i.e.:
- whenever you set a sprite (to be precise: a SpriteN[]-entry) to
- one of these three numbers, ANIVGA should cycle between the three
- sprite-images in the sequence 43->177->111->43->177->111->...
- You would then set NextSprite[43]:=177; NextSprite[177]:=111 and
- NextSprite[111]:=43 (don't forget this final value!) to do so.
-
- Note (!) : - Most often, you will have the situation that some sprite(load)-
- numbers with consecutive numbers should make up a cycle. In that
- case it is more convenient to use the SetSpriteCycle()-procedure
- to do the job for you
- - Again, note that the routine deals with spriteLOADnumbers! That
- is intentionally, because a sprite cycle is related to the
- _physical_ existent sprite data, or simply spoken: if you make
- 5 pictures to form a flickering torch and you are going to use
- 10 torches in your animation then each of them should loop
- through this 5-picture-cycle, shouldn't it?
- - NextSprite[] is initially set "to point to itself", that is:
- NextSprite[i]=i for all possible i's. If you had to break off
- a sprite cycle (though I can't think what this should be good
- for...), you must restore this data, e.g.: if you wanted to
- break the sprite cycle above, you would have to set
- NextSprite[43]:=43; NextSprite[177]:=177; NextSprite[111]:=43;
- - As this is a global variable, ANIVGA can't check whether your
- settings make sense or not; thus, it remains your responsibi-
- lity to use proper values!
-
- See also : SetSpriteCycle, Sprite cycles
-
-
- NMAX - constant
- ───────────────
-
- Function : Determines the maximum of sprites to be active at the same time
- (minus 1)
-
- Declaration: CONST NMAX=499
-
- Description: This constant sets the size of the internal tables - and thus the
- valid sprite numbers: the indices of the tables SpriteX, SpriteY
- and SpriteN must lie in the range 0..NMAX.
- To state it otherwise, there may be up to NMAX+1 sprites creeping
- around your screen at the same time...
-
- Note : Don't confound that constant with LoadMAX
-
- See also : LoadMAX
-
-
- OutTextXY - procedure
- ─────────────────────
-
- Function : Writes a textstring to the graphic screen
-
- Declaration: PROCEDURE OutTextXY(x,y:INTEGER; pa:BYTE; s:STRING); FAR;
-
- Description: ANIVGA has a built-in font, each character consisting of 6x6
- pixels: very ugly, but hey, we want to make animations, not text!
- To write the string "s" to the graphic screen, you must specify
- the upper left starting corner of the text in (x,y):
- (x,y) -> ▄──────────┐ , where (x,y) are virtual coordinates!
- │ │
- │ │
- │ │
- └──────────┘
- The text will be drawn in color GRAPHTEXTCOLOR and with the orien-
- tation GRAPHTEXTORIENTATION ("VERTICAL" or "HORIZONTAL").
- A third global variable, GRAPHTEXTBACKGROUND, specifies the color
- which will be used for the background area "beneath" the text
- letters; if GRAPHTEXTCOLOR=GRAPHTEXTBACKGROUND then the text will
- be drawn like TurboPascal's routine does: only the pixels be-
- longing to the letters will be drawn, all others remain unchanged.
- "pa" specifies the graphic page to be drawn on and must be one of
- the drawing pages (0 or 1) or the BACKGNDPAGE (=2) for background
- mode STATIC.
-
- Note : - In 99% of all cases, you will output text to the visible
- screen, that is: "OutTextXY(someX,someY,1-PAGE,'foobar')"
- - Any text drawn to the working pages 0 or 1 will stay onscreen
- only for one animation cycle. If you want it permanent, then
- use BackGroundOutTextXY() in mode STATIC or replace any call
- to Animate() by the sequence
- Animate();
- OutTextXY(someX,someY,1-PAGE,my_text)
- which works in both modes STATIC & SCROLLING. (As always, if
- you are in mode SCROLLING and use absolute coordinates, the
- text will scroll with your graphic image, while if you use
- relative coordinates (relative to StartVirtualX|Y of course),
- then the text will stay at a definite physical monitor position.
- For example,
- OutTextXY(StartVirtualX,StartVirtualY,1-PAGE,'Hi!')
- will tie the text to the upper left screen position)
- - Better fonts could have been developped, but they would all
- depend on special assumptions about the text- and/or background
- color(s).
- This font was intented for short and simple text strings and to
- be as small as possible.
- Nevertheless, using a bigger cell (say: 10x10) and several
- colors (for antialiasing effects) can result in very impressive
- fonts - and work, too...
- - Possible ERROR-values returned are: Err_InvalidPageNumber
-
- See also : GraphtextColor, GraphtextOrientation, GraphtextBackground,
- BackgroundOutTextXY
-
-
- PAGE - variable
- ───────────────
-
- Function : Holds the number of the actual drawing page
-
- Declaration: VAR PAGE:WORD
-
- Description: ANIVGA uses a page flipping approach. Basically this means that it
- alternates between using page 0 and page 1 for its display.
- Although this mechanism should be transparent for the user, ANIVGA
- provides you with the page number of the actual drawing page in
- "PAGE". Note that this number specifies always the invisible page:
- when PAGE=0, then the actual _displayed_ page is page 1 and vice
- versa (ANIVGA always works on the invisible page!).
-
- Note (!) : Only _read_ this value, never assign a new value to it!
-
-
- PAGEADR - variable
- ──────────────────
-
- Function : Holds the segment address of the actual drawing page PAGE
-
- Declaration: VAR PAGEADR:WORD
-
- Description: As already mentioned, there are four graphic pages, numbered from
- 0 to 3. The start addresses of these four pages are used by ANIVGA
- and normally the user should not need to reference them, but with
- PAGEADR at least the address of the actual (invisble) graphic page
- PAGE is available in PAGEADR.
-
- Note (!) : Only use this variable to _read_ its value, never change it!
- Although this 16-bit-value represents only the segment part of the
- complete address, it is the whole address: the address is norma-
- lized in such a way that the offset part is always zero.
-
- See also : PAGE
-
-
- PageGetPixel - function
- ───────────────────────
-
- Function : Returns the color value of the specified point
-
- Declaration: FUNCTION PageGetPixel(x,y:INTEGER; pa:BYTE):BYTE; FAR;
-
- Description: If the point at the virtual coordinates (x,y) and graphic page
- "pa" lies on the screen (i.e.: in the range (0,0)..(319,199) in
- absolute coordinates), this routine will return its color, if it
- is offscreen, the function returns zero.
- "pa" should be one of the values 0, 1 or BACKGNDPAGE (=2).
-
- Note : - If you want to read a pixels' color from the _visible_ page, you
- have to remember that it is the opposite of the _actual_ page
- (that is, you have to use "1-PAGE" as page number).
- - Although only values of 0,1 and BACKGNDPAGE (=2) make sense as
- "pa" values, the routine doesn't check that (for improved speed)
- - For that, the routine _doesn't_ return Err_InvalidPagenumber or
- something similiar in ERROR!
-
- See also : Background, Coordinates, GetPixel
-
-
- PagePutPixel - procedure
- ────────────────────────
-
- Function : Plots a point at a specified page
-
- Declaration: PROCEDURE PagePutPixel(x,y:INTEGER; color,pa:BYTE); FAR;
-
- Description: This routine is very similiar to PutPixel(), but it lets you
- specify explicitly on which graphic page the point shall be drawn.
- (x,y) specify the virtual coordinates of the point to be drawn in
- color "color". If this point lies onscreen (i.e.: its absolute
- coordinates are between (0,0)..(319,199)), it will be drawn on the
- specified page "pa", which must have one of the values 0, 1 or
- BACKGNDPAGE (=2). The latter only makes sense if STATIC is used as
- background mode.
-
- Note : - Don't forget that this routine works with virtual coordinates.
- - Note also that the point is _not_ drawn automatically on the
- background page if pa=0 or pa=1, thus it will be visible exactly
- one animation cycle (and be overdrawn by the background image
- then).
- - Because of ANIVGA's working scheme, you probably want to use
- this routine AFTER calling Animate() (else, your point would be
- overdrawn by the background image immediately) if pa=1-PAGE.
- If you want to draw the point at the _visible_ page, remember
- that it is the "opposite" of the _actual_ drawing page, i.e.:
- you have to use "1-PAGE" for "pa".
- - For improved speed, the routine _doesn't_ check the "pa"
- variable to have a valid value, so there will be no report to
- ERROR (Err_InvalidPageNumber or the like) available!
- It remains your responsibility to assure a proper value for pa!
-
- See also : BackgroundPutPixel, PutPixel, coordinates, How ANIVGA works
-
-
- Palette, PaletteEntry, PalettePtr - type
- ────────────────────────────────────────
-
- Function : Supplies user with proper internal data types
-
- Declaration: TYPE PaletteEntry=RECORD red,green,blue:BYTE END;
- Palette=ARRAY[0..255] OF PaletteEntry;
- PalettePtr=^Palette;
-
- Description: Drawing colors with the EGA/VGA is quite an interesting thing!
- You probably heard that "mode $13 gives you 256 out of 262144
- colors". The key to this is the palette (or, to be precise:
- the color-look-up-table "CLUT").
- Every color (in the range 0..255) is used as a pointer into the
- CLUT; the corresponding entry consists of three bytes, which
- stand for the red/green/blue intensity of that color (in that
- order!). These three "bytes" (only the values 0..63 are valid for
- each of them) together form an "PaletteEntry". Because we have
- 256 colors, a complete CLUT is made of 256 such entries: such a
- table will be called a "Palette" in ANIVGA!
-
- Note : ANIVGA initially assumes the default colors of mode $13.
- When you change the palette and you are using one of the display
- modes Display_SHADOW or Display_SHADOWEXACT, ANIVGA must know
- this, as it must recompute its ShadowTab. "SetPalette()" takes
- care of this, so you shouldn't change palettes by other means
- than "SetPalette()" until you are absolutely sure what you are
- doing!
-
- FYI: Note also that the 256 color modes are something special:
- in all other graphic modes (the EGA's 640x350x16 for example),
- there is a second, intermediate indirection level.
- There, the color value is used as an index into a table, giving
- a value between 0..63. This value is used again as an index into
- a second table which holds the triples ("PaletteEntries")
- mentioned above. The first table is called the palette, the second
- is the CLUT. In the 256 color modes, only the CLUT is used, but
- few of us ever heard of CLUTs! Because there is no way to confuse
- things in ANIVGA, I decided to use the term "palette"!
-
- See also : SetShadowTab, ShadowTab, DefaultColors, SetPalette, GetPalette
-
-
- Palette (*.PAL) files - information
- ───────────────────────────────────
-
- Palette files generated by GRAB and MAKES make it possible to use different
- colors than the BIOS default values, just by issuing a LoadPalette()-call.
- Their internal format is the simplest possible: each color consists of three
- bytes, specifying the RGB-values (in that order), where each value can reach
- from 0 (darkest) to 63 (brightest), e.g.: a bright red would be coded as
- (63,0,0).
- LoadPalette() reads in a complete palette - equally, if it is 3*16 bytes in
- size or the max. 3*256 bytes for a complete 256 color palette, but it is wise
- to use complete 256 color palettes, because otherwise you soon get confused,
- - don't say I didn't warn you!
-
- See also : LoadPalette(), Palette
-
-
- PutImage - procedure
- ────────────────────
-
- Function : Pastes a formerly copied image to the screen
-
- Declaration: PROCEDURE PutImage(x,y:INTEGER; p:POINTER; pa:WORD); FAR;
-
- Description: PutImage() is the counterpart of GetImage(): use GetImage() to
- copy part of the screen and PutImage to paste it somewhere. (x,y)
- is the upper left corner of the destination (in _virtual_ coordi-
- nates), "p" is the pointer given by GetImage() and "pa" is the
- number of the graphic page (0, 1 or BACKGNDPAGE (=2)) of the des-
- tination.
- If p equals NIL, the routine does nothing at all; this is useful
- because you can PutImage() directly on the result of a GetImage()
- call without further checking for clippings, although you should
- be careful by doing so: you don't get a "handle" this way which
- you could use to free up the occupied memory again!
- (See FreeImageMem() for more about that)
-
- Note : - Like GetImage(), this routine also works only when the _virtual_
- coordinates translate into _absolute_ coordinates in the range
- of 0..319, 0..199, that is: they must lie on the visible part of
- the screen, everything else is clipped off.
- - Possible ERROR-values returned are: Err_InvaliPageNumber
-
- See also : GetImage, FreeImageMem, coordinates
-
-
- PutPixel - procedure
- ────────────────────
-
- Function : Plots a point
-
- Declaration: PROCEDURE PutPixel(x,y:INTEGER; color:BYTE); FAR;
-
- Description: (x,y) specify the virtual coordinates of the point to be drawn in
- color "color". If this point lies onscreen (i.e.: its absolute
- coordinates are between (0,0)..(319,199)), it will be drawn on the
- visible page 1-PAGE.
-
- Note : This routine is not the same as TurboPascal's one: it works with
- virtual coordinates! Note also that the point is _not_ drawn on
- the background page, thus it will be visible for exactly one ani-
- mation cycle (and be overdrawn by the background image then).
- Because of ANIVGA's working scheme, you probably want to use this
- routine AFTER calling Animate() (your point will then be visible
- until the next call to Animate()).
-
- See also : BackgroundPutPixel, PagePutPixel, coordinates, How ANIVGA works
-
-
- PutTile - procedute
- ───────────────────
-
- Function : "Pastes" a tile into the background image
-
- Declaration: PROCEDURE PutTile(x,y:INTEGER; TileNr:BYTE); FAR;
-
- Description: After you have defined a background scrolling area, you can use to
- PutTile() to arrange them as wanted to build your background image.
- (x,y) is the virtual coordinate where you want the tile "TileNr"
- to be placed.
- (x,y) will be changed to be a multiple on 16 in each direction
- and must then lie in the range (BackX1,BackY1)..(BackX2,BackY2).
-
- Note : - Of course, this routine only makes sense when you use background
- mode SCROLLING!
- - (x,y) will be drawn to the upper left to fall on the grid.
- - Possible ERROR-values returned are: Err_InvalidCoordinates
-
- See also : background, tile, SetBackgroundScrollRange, coordinate, BackX1,
- BackX2, BackY1, BackY2
-
-
- Screen - procedure
- ──────────────────
-
- Function : Chooses the display page.
-
- Declaration: PROCEDURE Screen(pa:BYTE) FAR;
-
- Description: Call Screen() with a value between 0 and 3 which tells the routine
- to which graphic page it should switch. This is done by repro-
- gramming the VGA start address registers. For a flickerfree dis-
- play, this switching is synchronized to the display enable signal.
-
- Note (!) : - You should not use this routine if you are not absolutely sure
- what you are doing! Be aware that ANIVGA relies on the fact that
- the actual drawing page is PAGE and its segment address is in
- PAGEADR while the actually visible page is 1-PAGE!
- - Although it makes little sense to apply this routine to graphic
- pages other than 0 or 1, it is possible to set "pa" to 2 (=BACK-
- GNDPAGE) or 3 (=SCROLLPAGE).
-
- See also : PAGE, PAGEADR, InitGraph
-
-
- ScrollPage - constant
- ─────────────────────
-
- Function : Holds the page number of the backround page
-
- Declaration: CONST SCROLLPAGE=3;
-
- Description: When using background mode SCROLLING, BackGndPage specifies the
- page number of the tile buffer used to build up the background
- image for animations.
-
- Note (!) : Use of this constant only makes sense when using background mode
- SCROLLING!
-
- See also : BackGndPage, Background
-
-
- SetBackgroundMode - procedure
- ─────────────────────────────
-
- Function : Chooses one of the possible background modes of ANIVGA
-
- Declaration: PROCEDURE SetBackgroundMode(mode:BYTE); FAR;
-
- Description: ANIVGA has two possible ways of handling background you can choose
- of: "STATIC" or "SCROLLING" backgrounds with several advantages
- and disadvantages, each (see background). Specify the mode you
- want to use in the "mode" variable.
-
- Note : - Default value set by ANIVGA is STATIC.
- - Possible ERROR-values returned are: Err_InvalidMode
-
- See also : background
-
-
- SetBackgroundScrollRange - procedure
- ────────────────────────────────────
-
- Function : Specifies the scrollable background area in mode SCROLLING
-
- Declaration: PROCEDURE SetBackgroundScrollRange(x1,y1,x2,y2:INTEGER) FAR;
-
- Description: (x1,y1) is the upper left corner of the background scroll area,
- (x2,y2) the lower right corner (all virtual coordinates).
- ANIVGA will round the points given to fit on a grid with mesh 16,
- that is, x1,y1,x2,y2 will be changed to be all multiples of 16.
- These new values will be stored in the (global) variables BackX1,
- BackY1, BackX2, BackY2 for further use.
- Besides that, XTiles and YTiles will hold the width and height of
- the choosen background area in tiles.
-
- Note : - You can read the Back??-variables for your information, but
- don't change them!
- - Of course, this routine only makes sense when you are going to
- use SCROLLING as background mode.
- - The upper left corner (x1,y1) will be drawn to the upper left,
- the lower right corner (x2,y2) to the lower right to fall on the
- grid.
- - Don't forget that the tile memory is limited; you can't select
- an area bigger than MaxTiles (=10000) tiles, that is more than
- 2560000 pixels².
- - Possible ERROR-values returned are: Err_InvalidCoordinates and
- Err_BackgroundToBig
-
- See also : background, tiles, PutTile
-
-
- SetCycleTime - procedure
- ────────────────────────
-
- Function : Defines the maximum animation speed
-
- Declaration: PROCEDURE SetCycleTime(milliseconds:WORD); FAR;
-
- Description: There are lots of PC-compatible machines with a broad range of
- clock rates, wait states and different speeds of their graphic
- cards. With this routine you can set the time an animation cycle
- has to last at least: at the very end of Animate, the routine
- checks whether at least "milliseconds" milliseconds have been past
- since the last call to this routine and waits if necessary.
- If you give 0 milliseconds as an argument or your machine is not
- (at least) an AT class machine, there will be no such time control
- mechanism and the animation will always take part at the maximal
- speed on the specific machine (this is also the default value).
-
- For example: "SetCycleTime(100);" would restrict the animation
- rate even on the fastest 80586 machines to at most 1sec/100msec
- = ten frames per second.
-
- Note (!) : - Because there is no such high precision timer on PC/XT computers
- as required, SetCycleTime() is ignored on these machines.
- Anyway, this should be not to hard because these computers are
- normally that slow that they would not have been slowed down
- either.
- - The accuracy of this timing mechanism is better than 1 milli-
- second.
-
-
- SetModeByte - procedure
- ───────────────────────
-
- Function : Specifies the way a sprite will be displayed
-
- Declaration: PROCEDURE SetModeByte(Sp:WORD; M:BYTE); FAR;
-
- Description: This routine assigns one of the possible display methods "M"
- (Display_NORMAL, Display_FAST, Display_SHADOW,
- Display_SHADOWEXACT)
- to the specified spriteLOADnumber "Sp".
-
- Note : - Because this kind of information is stored directly inside the
- sprite data, the sprite must have been loaded already for this
- routine to work.
- - For the same reason, the routine works on spriteLOADnumbers,
- not sprite numbers (>gee, again!<): a display method set for one
- spriteLOADnumber will affect all sprites with that LOADnumber!
- Most often, that is okay (e.g.: if you use the sprite of a foot-
- ball player ten times, it is quite normal to use the same dis-
- play mode for all ten players!), if you really must use a sprite
- with two different display methods at the same time, you can use
- the following trick: load the sprite's data a second time into
- memory, using a different spriteLOADnumber. For this new copy,
- you can use another display mode.
- - Possible ERROR-values returned are: Err_InvalidSpriteNumber and
- Err_InvalidMode
-
- See also : SpriteLoadNumber, SpriteNumber, Display methods, GetModeByte
-
-
- SetOffscreenTile - procedure
- ────────────────────────────
-
- Function : Defines the tile to be used outside the specified scroll range
-
- Declaration: PROCEDURE SetOffscreenTile(TileNr:BYTE); FAR;
-
- Description: When you use background mode SCROLLING and have set up a scroll
- range (via SetBackgroundScrollRange() ), all tiles _within_ that
- region are specified by your settings done with PutTile().
- However, ANIVGA must know what to draw when it has to display
- areas _outside_ that "window": you can choose that tile with
- SetOffscreenTile().
- Example: You set your scrollable background range by issuing
- SetBackgroundScrollRange(-500,-500,1000,1000) and used PutTile()
- to define that tiles 0..10 (say) should be used inside that
- window (-500,-500,1000,1000) in some specific order. If you want
- that everything outside the window should be painted with tile
- 6 (say), you would tell ANIVGA so by calling SetOffscreenTile(6)
-
- Note : - The default value set by ANIVGA is 0
- - Of course, using this procedure only makes sense when using
- background mode SCROLLING!
-
- See also : SetBackgroundScrollRange, PutTile, Background
-
-
- SetPalette - procedure
- ──────────────────────
-
- Function : Changes the VGA's color values
-
- Declaration: PROCEDURE SetPalette(pal:Palette; update:BOOLEAN); FAR;
-
- Description: You can use this procedure to change the color values of the VGA's
- 256 colors by supplying an appropriate palette.
- "update" tells the procedure whether it should recompute its
- internal "ShadowTab" or not; if you use one of the two display
- modes Display_SHADOW or Display_SHADOWEXACT you must set this
- value to TRUE or the shadow areas will show "wrong" colors
- (namely the old ones *before* changing the palette). If you don't
- use shadowing (or change colors in a way so that using the old
- shadow is okay), you can use FALSE and save some time.
-
- Note : - SetPalette automatically updates "ActualColors" to reflect the
- changes made; although you don't have to use the variable
- "ActualColors" as first parameter of this procedure, you are
- recommended to do so, that is
- a) make your color changes to ActualColors[]
- b) call SetPalette(ActualColors,TRUE|FALSE)
- This way, you will save some time and the memory requirements
- for an additional palette
- - If you messed up things, use "SetPalette(DefaultColors,TRUE)" to
- return to the default values.
- - You must be in graphic mode already or strange things may happen
- (at least, you won't get the colors you intented...)
- To state in otherwise: call this routine _after_ having called
- InitGraph() and _before_ calling CloseRoutines()!
-
- See also : GetPalette, Palette, LoadPalette, ActualColors
-
-
- SetShadowTab - procedure
- ────────────────────────
-
- Function : Set the amount of shadowing in display modes Display_SHADOW and
- or Display_SHADOWEXACT
-
- Declaration: PROCEDURE SetShadowTab(brightness:BYTE); FAR;
-
- Description: Whenever a sprite is drawn in Display_SHADOW / Display_SHADOWEXACT
- mode, ANIVGA must know how much darker these shadow areas should
- be, compared with the brightness of the original (not-shadowed)
- colors.
- This data is held in the table ShadowTab and is set by default to
- 70% of the colors original brightness. However, you can use this
- routine to provide more or less darker shadow areas: "brightness"
- is the percentage of the colors original brightness which shall
- remain, e.g.: brightness=0 would mean every shadow is completely
- black, brightness=100 is the original color as shadow (not darken-
- ed at all), brightness=40 will darken every color by 100-40=60%,
- etc.
-
- Note (!) : - SetShadowTab() bases its computation on the actually displayed
- colors, held in the table "ActualColors"
- - This routine takes app. 1s on an 8MHz AT. This can be quite a
- "long" time when you are in midst of a smooth animation sequence
- -or doesn't bother you at all (e.g., in the very beginning of
- your program) - this depends on your applications!
- - The argument will be only approximated: the algorithm computes
- the 256 color values needed precisely and matches them as close
- as possible to the 256 colors actually set.
- Note that the palette registers of the VGA card *won't* be
- changed at all! ANIVGA still works with the default VGA palette
- of the BIOS (or whatever values you set); what it does is
- solely creating an internal color look-up-table!
- - Possible ERROR-values returned are: Err_InvalidPercentage
-
- See also : ShadowTab, ActualColors, Display modes, SetModeByte
-
-
- SetSpriteCycle - procedure
- ──────────────────────────
-
- Function : Links spriteLOADnumbers together to form a sprite cycle
-
- Declaration: PROCEDURE SetSpriteCycle(nr,len:WORD); FAR;
-
- Description: "nr" is the first spriteLOADnumber to be included in the sprite
- cycle and "len" entries (i.e.: from "nr" to "nr+len-1") should be
- tied together.
- The routine will then set the according NextSprite[] entries to
- build this cycle: nr -> nr+1 -> nr+2 -> ... -> nr+len-1 -> nr
-
- Note : - The routine uses spriteLOADnumbers, _not_ sprite numbers!
- - If you want to link sprite(loadnumber)s which do not have conse-
- cutive (load)numbers, you must do that by setting NextSprite[]
- accordingly.
-
- See also : Sprite cycles, NextSprite
-
-
- ShadowTab - "procedure"
- ───────────────────────
-
- Function : Table for translating sprite colors into others
-
- Declaration: PROCEDURE ShadowTab; FAR;
-
- Description: If the display mode "Display_SHADOW" is set for a physical
- sprite, its colors will depend not on the values stored in the
- sprite itself, but on the values found on the screen at the place
- where the sprite shall be drawn: every pixel of the sprite will
- become darkened by substituting its corresponding color against
- the color stored in this color table. (Mode "Display_SHADOWEXACT"
- behaves the same, but shadowing will take place only at points
- with sprite color <>0 - that's the whole difference).
- At startup, this table is set to make shadows be approximately
- 70% the brightness of the original colors, but you can adjust
- this with the routine SetShadowTab() if this value is not sui-
- table for your application.
- You can even supply a completely different color table (for
- special effects?).
- To do so, define an array "[0..255] of byte" (you should use the
- predefined TYPE ColorTable for this), containing for each color
- of the standard palette its substitute (e.g. setting array
- element [8]:=13 would mean: "replace every pixel in the shadow
- area with color 8 against a pixel with color 13") and overwrite
- the original color table by issuing the command
- "MOVE(my_array,@ShadowTab^,256)"
-
- Note : - Although this table is declared as a procedure, it really is
- data, not code; so don't call it!
- - There can be only _one_ color table and it is only active in
- display modes "Display_SHADOW" or "Display_SHADOWEXACT".
-
- See also : SetShadowTab, Display modes, SetModeByte
-
-
- SPRITE, Spritenumbers, Spriteloadnumbers - information
- ──────────────────────────────────────────────────────
-
- A sprite is the basic data element used in ANIVGA. Technically spoken, it is
- nothing more then a two-dimensional array of bytes which becomes copied to the
- screen positions needed, but it is far more comprehensive to think about it as
- a photograph of a figure which can be pasted to the screen whereever you want.
- To distinguish between different sprites, we use natural numbers, but whenever
- we talk about "sprites", we are somehow inaccurate:
- You should notice that there are two kinds of "sprite numbers" which should
- not be mixed up: one is a spriteLOAD number and represents a handle to the
- (physical) sprite data, while the other (normally termed "sprite number") is
- a logical number to address the sprite data.
- Yet, most often it is clear from the context, which meaning is intended:
- For a simple example: if you are going to animate a soccer team, you would
- need 11 sprites for the player - but they all have the same shape. This means,
- you only have to load one sprite (-> you need 1 spriteLOAD number), but need
- 11 copies of that image to move around the screen (-> you need 11 sprite
- numbers).
- (See section "How ANIVGA works" for more about that)
- You can design sprites with the help of the spritemaker-tool MAKES, by using
- GRAB to capture and convert graphic screens from other graphic applications
- or write your own tools for that (it's really not that difficult you think
- it is...).
-
- See also : sprite format, How ANIVGA works
-
-
- SPRITE CYCLES - information
- ───────────────────────────
-
- Often, you don't want to have a single picture as sprite, but a sequence of
- them which should loop forever. For example, let's assume that you use a torch
- as an animation object in your application and you want it to have a flicker-
- ing flame.
- You would start to draw 5 (say) pictures, which -repeatedly displayed one
- after another- would make the impression of your flickering torch. But within
- your application, you still want to handle these five different images as one
- single object - namely the sprite "torch".
- To do so, you can use a capability of ANIVGA, called a "sprite cycle": load
- the five images as (physical) sprites and tie their loadnumbers together to
- form that sequence!
- The easiest way to do that would be to load the images with consecutive
- numbers and use the SetSpriteCycle() procedure to form the sprite cycle (see
- there).
- Note that we are talking about linking spriteLOADnumbers here: when you have
- built such a cycle for your torch and you want to use 10 torches in your
- program, you surely want that each of them behaves the same, that is: they all
- should show a flickering flame by using that sprite cycle.
- For this reason, ANIVGA uses spriteLOADnumbers, so that every instantiation of
- a spriteLOADnumber (i.e.: a SpriteN[]-entry) belonging to a cycle will lead to
- a sprite cycle for this sprite! (Tip: in out torches example, it would be wise
- to use different starting values for the 10 torches, so that they do not
- flicker "in phase")
- A small detail at last: if you defined a sprite cycle to be a->b->c->a->...,
- and initialized a SpriteN[]-entry to "a", then the first sprite displayed at
- the screen will be "b" instead of "a" - why?
- Well, ANIVGA handles sprite cycles in the Animate() routine and thus has two
- possibilities to update the SpriteN[]-table (by issuing a "SpriteN[] :=
- NextSprite[SpriteN[]]" command): _before_ drawing the sprites or _afterwards_.
- But when it does _after_ drawing the sprites, the sprites displayed on your
- screen (=the old SpriteN[] values before doing the above command) are incon-
- sistent to the according numbers actually held in the SpriteN[]-table!
- This could lead to problems (e.g.: when you do a HitDetect() after calling
- Animate()). Although this could be circumvented by a special grouping of sub-
- routine calls, it is far more convenient to update the SpriteN[]-table
- _before_ drawing the sprites.
- The only drawback with this method is the one stated in the beginning: not the
- SpriteN[]-entry supplied by you will be drawn, but its "successor"
- NextSprite[SpriteN[]]!
- However, most often that won't be that bad and *if* it would, you still could
- compensate for it by using the sprite's predecessor (in the above example, you
- would use "c", as it is the predecessor of "a", to display "a").
-
-
- SPRITE FORMAT - information
- ───────────────────────────
-
- As already said, a sprite is nothing more then a two-dimensional array of
- bytes which becomes copied to the screen positions needed.
- For quick animations, the data should be stored in a format which causes few
- and simple transformation steps when accessing the data, but it is hard to
- keep up with that principle, because the graphic mode used is "planed".
- This means that points are _not_ stored sequentially into the graphics memory,
- but in a rather strange way: every 4 points use the same address, but lie in
- different "bitplanes". To cut it short: clipping and drawing sprites is hell
- therefore (and surely one reason why there are so less tools for this mode)
- and ANIVGA uses a very special format to store a sprite (= *.COD-files):
-
- 0..1 DW offset to Plane_0_Data (points with x-coord. MOD 4=0)
- 2..3 DW offset to Plane_1_Data (points with x-coord. MOD 4=1)
- 4..5 DW offset to Plane_2_Data (points with x-coord. MOD 4=2)
- 6..7 DW offset to Plane_3_Data (points with x-coord. MOD 4=3)
- 8..9 DW sprite width (DIV 4), rounded up if not dividable by 4
- 10..11 DW sprite height in lines
- 12..15 DB 1,2,4,8 ; constants (translate-table)
- 16..17 DW SpriteLength ; length of this sprite file
- 18..37 DW 10 dup(?) ; reserved area for future use
- 38..39 DB 'K','R' ; code for "this is a sprite file"
- 40 DB 1 ; version
- 41 DB 0 ; default display mode (0=Display_NORMAL)
- 42..43 DW offset pointer to left boundary table
- 44..45 DW offset pointer to right boundary table
- 46..47 DW offset pointer to top boundary table
- 48..49 DW offset pointer to bottom boundary table
- 50..SpriteLength-1: boundary- and plane data tables
-
- (If you should wonder why all pointers are only 16 bit long: the maximal size
- of one sprite is 64k, so offset pointers are sufficient.
- Another trick is that ANIVGA loads sprites at segment boundaries; for that,
- you don't have to distinguish between "relative offsets" and "offset poin-
- ters": if normalized segment addresses (=offset part is ε [0..15]) are used
- to address sprites, the offset part is always 0, so the two terms are
- identical!)
-
- The Plane_?_Data tables consist of the points of the sprite (1 pixel = 1 byte);
- if the sprite width is 12 pixels (say), then each table would hold 12/4=3 bytes
- for each of the sprite's rows:
- Plane_0_Data = color of pixels 0,4,8 of 1. sprite row
- color of pixels 0,4,8 of 2. sprite row
- ...
- Plane_1_Data = ditto, for pixels 1,5,9
- Plane_2_Data = ditto, for pixels 2,6,10
- Plane_3_Data = ditto, for pixels 3,7,11
-
- The boundary tables hold the outermost positions of the sprite:
- The left/top/right/bottom boundary table holds the leftmost/topmost/
- rightmost/bottomost pixel of each row/column/row/column (or 16000/16000/
- -16000/-16000 if none exists), respectively:
- left boundary table = leftmost pixel coordinate of 1. sprite row (or 16000)
- leftmost pixel coordinate of 2. sprite row (or 16000)
- ...
- Note that each entry in the boundary tables consists of a signed integer!
-
- Note also that sprites are always stored as the smallest, the figure including
- box (rounded up in the x-direction to the next multiple of 4), but that the
- values of the "superfluous points" stored in the plane tables doesn't matter
- at all (no difference which display mode is used for the sprite!), because
- ANIVGA uses only the bytes of the areas which belong to the _real_ sprite-
- figure (ANIVGA determines these parts by assuming the sprite to be "horizontal
- convex" and uses the boundary tables to compute them).
- (Don't worry if you do not understand these technical details now --hopefully,
- you won't need them at all).
-
- See also : MAKES, Display modes, convex, sprite library
-
-
- SPRITE LIBRARY - information
- ────────────────────────────
-
- Sprite files can be combined to sprite libraries. The main advantage of this
- is that you can reduce the number of files needed for your programs drama-
- tically:
- A normal program will use approximately 20..40 different sprites, so that you
- would have 20..40 files only for your sprites!
- But ANIVGA's routine to load sprites "loadSprite()" is flexible enough to dis-
- tinguish whether the file to be loaded contains one or more sprites and loads
- them all.
- To construct such a "sprite library" (suggested filename extension: .LIB), you
- just use MSDos' COPY-command with the binary option "/B" to glue the binaries
- together; for example:
-
- COPY /B sprite1.cod+d:\sprites\sprite2.cod+testspr.cod A:\mylib.lib
-
- would concatenate the three sprites "sprite1.cod", "d:\sprites\sprite2.cod"
- and "testspr.cod" and build the sprite library "A:\mylib.lib".
-
- Note : You can reverse this process with the UNLIB-utility.
-
- See also : UNLIB, sprite format, loadSprite
-
-
- SpriteAd - variable
- ───────────────────
-
- Function : Store the pointers to the sprites' data
-
- Declaration: VAR SPRITEAD:ARRAY[0..LoadMAX] OF WORD;
-
- Description: Whenever you load a (physical) sprite with LOADnumber xxx, ANIVGA
- stores the sprite's data somewhere in RAM and maintains a pointer
- which points to the beginning of this data as a handle to access
- the data: this handle is stored in SpriteAd[xxx] and reflects the
- segment part of the starting address of the data.
-
- Note : Don't change that data directly unless you are absolutely sure
- what you are doing!
-
- See also : LoadSprite, SPRITE, Sprite Format
-
-
- SPRITEN, SPRITEX, SPRITEY - tables
- ──────────────────────────────────
-
- Function : Hold the values of all sprites to be drawn in the next animation
- cycle.
-
- Declaration: VAR SpriteN:ARRAY[0..NMAX] of Integer (SpriteX/Y dto.)
-
- Description: ANIVGA is based on tables: in SpriteN[] you must declare, which
- sprites shall be drawn in the next animation step. To do that,
- store the spriteLOAD number of the sprites into the SpriteN[]-
- entries; a zero indicates that the according sprite is inactive
- and should not be displayed.
- For every active sprite (SpriteN[i]<>0), a pair of virtual coor-
- dinates in the range -16000..+16000 must be specified in the
- SpriteX[i] and SpriteY[i] entries to determine the sprites' po-
- sition on the (virtual) screen.
- These coordinates will be transformed internally into real coor-
- dinates to decide whether the sprite is onscreen and has to be
- displayed or not.
-
- Note : If you have less sprites than are allowed by the system (that is:
- less than NMAX+1), your decision what table entries you use are
- arbitrary; if for example you have only two sprites, it won't
- matter, if you use SpriteN[0] for the first one and SpriteN[1]
- for the other or vice versa, or SpriteN[123] and SpriteN[310] or
- whatever valid indices you can think of - except in one point:
- the sprites are drawn in reverse order, that means SpriteN[NMAX]
- is drawn first, then SpriteN[NMAX-1] ... SpriteN[0].
- For that, if two (or more) sprites overlap each other, the one
- with the smallest index is drawn topmost and covers the other(s).
-
- For performance reasons you should observe another rule: if you
- use different display methods for different sprites then try to
- group your sprites in such a way, that sprites with the same dis-
- play method have continous indices. As an example: if the sprites
- with (load)number 1 use one method and the ones with number 2
- another, then the sequence SpriteN[]=(...2,2,2,2,2,...,1,1,1...)
- would be better than (...2,2,1,2,...,1,2,...,1,2,...).
- This is due to the fact that whenever ANIVGA has to draw a sprite
- with a display method other than the active one, it must inter-
- nally switch from one method to the other which costs some time.
-
- See also : SetModeByte
-
-
- StartVirtualX, StartVirtualY - variables
- ────────────────────────────────────────
-
- Function : Specify the upper left corner of the visible world
-
- Declaration: CONST StartVirtualX:INTEGER=0;
- StartVirtualY:INTEGER=0;
-
- Description: When working with virtual coordinates, your screen displays only
- a very small window (320x200 points) of this "virtual screen"
- (32000x32000 points). To tell ANIVGA which part of this virtual
- screen is to be displayed, you specify the upper left corner of
- the visible part in (StartVirtualX,StartVirtualY).
- For example, setting (StartVirtualX,StartVirtualY) to (100,1000)
- would define that the part of the virtual screen having x-coordi-
- nates ε [100..100+XMAX] and y-coordinates ε [1000..1000+YMAX] to
- be displayed.
-
- Note : Setting these variables doesn't affect the HitDetect-function: if
- two sprites collide outside the visible area, it will be detec-
- ted, still.
-
- See also : coordinates
-
-
- Table - TYPE
- ────────────
-
- Function : Supply a data type for the animation variables
-
- Declaration: TYPE Table=ARRAY[0..NMAX] OF INTEGER;
-
- Description: A lot of variables in ANIVGA have to be of type "one entry for
- each sprite" and "Table" is the appropriate form for that.
-
- Note : -
-
- See also : SpriteX, SpriteY, SpriteN
-
-
- Tile - information
- ──────────────────
-
- "Tiles" are graphic images, 16 pixels wide and high. They are used to define a
- scrollable background image when you use SCROLLING as background mode.
- Due to memory limitations, it is impossible to hold a complete background
- image in memory (because virtual coordinates range 32000 pixels in x/y-direc-
- tions, one would need app. 977 MB (!) RAM for that).
- Instead, you may define up to 256 different tiles and then combine them to
- form the graphic background, which may consist of up to MaxTiles (=10000)
- tiles (using the 256 different tiles).
- (A simple example for that can be found by "Background").
- ANIVGA stores tiles in a slightly different format then sprites internally,
- but you don't have to bother your head about that: on disk, tiles have the
- same format as sprites, so you can use all the utility programs to create/edit
- sprites also to create/edit tiles! The only restriction you have to care about
- is, that a tile has the definite size of 16 pixels in each direction (but see
- the LoadTile()-function for some simplifications about even that).
-
- See also : Background, LoadTile
-
-
- TRANSLAT - utility
- ──────────────────
-
- I hate doing work twice - that's why I have bought a PC! And it is the reason
- why... a) I invented TRANSLAT
- b) I'll just *cite* a few words from my own docs to TRANSLAT here:
-
- >TRANSLATE is a (quite dumb) translation program. It reads in a Pascal source
- >file, filters out all comments and tries to translate them into another
- >language by using a database "dictionary". It then writes out a new Pascal
- >file with the translated comments in it.
- >TRANSLATE is thought for all those programmers among us, whose native tongue
- >isn't English but who realized that this is the only universal language to
- >publish programs. I think most of us don't have problems to write program
- >docs and other accompanying texts in English. The problem lies within the
- >program sources: the comments of a program should serve two purposes: help
- >YOU, the author, to remember the thoughts you had when writing these lines
- >of code and second, help OTHERS to understand your program.
- >As being quite close to the thinking process in the human brain, I'm sure
- >that most of us are not willing to write down their program comments other
- >than in their native language! But when it comes to publish the program
- >sources, you'd better have them in English, as this is the only universally
- >understood language.
- >
- >Now you could maintain a second version of the program, identical to your
- >original, but with all comments translated to English -- but >uaaah!< if you
- >ever had to manage the consistency of two program versions of an evolving
- >project, you _surely_ know that this is like putting the plagues back into
- >Pandora's box!
- >So why not setting up a database for your comments and then run a program
- >which translates these comments? Well, TRANSLATE is exactly that program!
-
- Creating such dictionaries doesn't have to concern you (not until you would
- like to use it for your own sources; if so then drop me a note) -- just use
- it:
- TRANSLAT ANIVGA.PAS ANIVGA.NEW ANIVGA.DIC
-
- ...will create an English version of ANIVGA, named ANIVGA.NEW!
- (It takes quite a long time (~1h) for this, so if you have a multitasking en-
- vironment, then run it in the background!)
- If everything worked and ANIVGA.NEW compiles ok, then you can use ANIVGA.NEW
- to replace the German version ANIVGA.PAS (and delete TRANSLAT.EXE and
- ANIVGA.DIC).
-
- Note : - You can use _the same_ dictionary to translate ANIVGA V1.0, too
- - I didn't publish the complete TRANSLAT-package til now; con-
- sider the version included a "working α-version": it is just
- intended for the above command line. You are free to experi-
- ment with it, but if you ruin your system, don't say I didn't
- warn you! B-p
-
-
- UNLIB - utility
- ───────────────
-
- Sometimes, you will want to reverse the process of building a sprite library,
- that is: you want to split a sprite library into the sprite files of which it
- consists.
- To do that, call UNLIB with the name of the sprite library to split. UNLIB
- will then create the files UNLIB000.COD, UNLIB001.COD, UNLIB002.COD,... which
- represent the sprite files wanted.
- Note here that UNLIB cannot restore the original filenames you used (there is
- no such entry in a sprite's header). For that, it is a good idea to write down
- the names and sequence of the sprite files used in building a sprite library.
- (If you didn't, you still can load every extracted sprite with MAKES, look at
- it and give it the right name then)
-
- See also : sprite library, MAKES, sprite format
-
-
- VIRTUAL COORDINATES - information
- ─────────────────────────────────
-
- See : coordinates
-
-
- WriteBackgroundPage - procedure
- ───────────────────────────────
-
- Function : Saves the background image to disk
-
- Declaration: PROCEDURE WriteBackgroundPage(name:STRING); FAR;
-
- Description: This is merely a shortcut of the WritePage()-procedure (see
- there), i.e. WritePage(name; BACKGNDPAGE) would do an equivalent
- job.
-
- Note : Possible ERROR-values returned are Err_FileIO
-
- See also : WritePage
-
-
- WritePage - procedure
- ─────────────────────
-
- Function : Saves a graphic page to disk
-
- Declaration: PROCEDURE WritePage(name:STRING; pa:BYTE); FAR;
-
- Description: To save an image of one of the drawing pages (0 or 1) or the
- backgroundpage BACKGNDPAGE (=2), specify the approriate page
- number in "pa" and a valid MSDOS-path/name where to store the
- data in "name".
-
- Note : - Make sure that your disk has enough space to hold the data: one
- page is stored as 64003 bytes!
- - You can't use this procedure for saving the background page
- "pa"=SCROLLPAGE in background mode SCROLLING!
- - Possible ERROR-values returned are: Err_InvalidPageNumber and
- Err_FileIO
-
- See also : WriteBackgroundPage, LoadPage
-
-
- XMAX - constant
- ───────────────
-
- Function : Specifies the maximal absolute x-coordinate
-
- Declaration: CONST XMAX=319
-
- Description: XMAX is the biggest _absolute_ coordinate in the x-direction
- which can be used: all x-coordinates must lie in the range
- 0..XMAX.
-
- Note : Probably, you will never use this constant at all, because nearly
- everything in ANIVGA's user interface works with _virtual_ coor-
- dinates, but who can tell...
-
- See also : YMAX, coordinates
-
-
- XTiles - variable
- ─────────────────
-
- Function : Holds the width of the scrollable background image in tiles
-
- Declaration: VAR XTiles:INTEGER;
-
- Description: When using background mode SCROLLING, you have to specify the
- size of your scrolling background area (with the
- SetBackgroundScrollRange()-procedure). ANIVGA adjusts these
- values slightly and computes the size of the resulting background
- image in tiles.
- The width of this area (in tiles) is then stored in XTiles.
-
- Notes : Don't change this variable directly!
-
- See also : YTiles, Background, SetBackgroundScrollRange
-
-
- YMAX - constant
- ───────────────
-
- Function : Specifies the maximal absolute y-coordinate
-
- Declaration: CONST YMAX=199
-
- Description: YMAX is the biggest _absolute_ y-coordinate which may be used,
- that is, every y-coordinate must lie in the range 0..YMAX.
-
- Note : Probably, you will never use this constant at all, because nearly
- everything in ANIVGA's user interface works with _virtual_ coor-
- dinates, but who can tell...
-
- See also : XMAX, coordinates
-
-
- YTiles - variable
- ─────────────────
-
- Function : Holds the height of the scrollable background image in tiles
-
- Declaration: VAR YTiles:INTEGER;
-
- Description: When using background mode SCROLLING, you have to specify the
- size of your scrolling background area (with the
- SetBackgroundScrollRange()-procedure). ANIVGA adjusts these
- values slightly and computes the size of the resulting background
- image in tiles.
- The height of this area (in tiles) is then stored in YTiles.
-
- Notes : Don't change this variable directly!
-
- See also : XTiles, Background, SetBackgroundScrollRange
-