5740 lines
236 KiB
Plaintext
5740 lines
236 KiB
Plaintext
Hello there.
|
||
|
||
My name is Denthor (Grant Smith) of the South African demo group ASPHYXIA.
|
||
This is a trainer that have been writing on and off for the last few months
|
||
in order to help out budding young graphics programmers. Currently there are
|
||
nine tutorials in all, each with a text file and accompianing pascal source
|
||
file. Also included are two or three "bonus" pascal files with various
|
||
effects.
|
||
|
||
I have left the files in their origional form, so they contain some local
|
||
stuff which you can ignore.
|
||
|
||
PLEASE LEAVE A RESPONSE! Any comments/criticisms/flames/suggestions etc are
|
||
very welcome (I love getting mail!)
|
||
|
||
Leave all comments to smith9@batis.bis.und.ac.za
|
||
|
||
Hope to hear from you soon!
|
||
|
||
--
|
||
DENTHOR, coder for ...
|
||
_____ _____ ____ __ __ ___ ___ ___ ___ __ _____
|
||
/ _ \ / ___> | _ \ | |_| | \ \/ / \ \/ / | | / _ \
|
||
| _ | \___ \ | __/ | _ | \ / > < | | | _ |
|
||
\_/ \_/ <_____/ |__| |__| |__| |__| /__/\__\ |__| \_/ \_/
|
||
smith9@batis.bis.und.ac.za
|
||
The great South African Demo Team! Contact us for info/code exchange!
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 1 ]==--
|
||
|
||
|
||
|
||
þ Introduction
|
||
|
||
|
||
|
||
Hi there! This is Denthor of ASPHYXIA, AKA Grant Smith. This training
|
||
program is aimed at all those budding young demo coders out there. I am
|
||
assuming that the reader is fairly young, has a bit of basic Std. 6 math
|
||
under his belt, has done a bit of programming before, probably in BASIC,
|
||
and wants to learn how to write a demo all of his/her own.
|
||
|
||
This I what I am going to do. I am going to describe how certain routines
|
||
work, and even give you working source code on how you do it. The source
|
||
code will assume that you have a VGA card that can handle the
|
||
320x200x256 mode. I will also assume that you have Turbo Pascal 6.0 or
|
||
above (this is because some of the code will be in Assembly language,
|
||
and Turbo Pascal 6.0 makes this incredibly easy to use). By the end of
|
||
the first "run" of sections, you will be able to code some cool demo
|
||
stuff all by yourself. The info you need, I will provide to you, but it
|
||
will be you who decides on the most spectacular way to use it.
|
||
|
||
Why not download some of our demos and see what I'm trying to head you
|
||
towards.
|
||
|
||
I will be posting one part a week on the Mailbox BBS. I have the first
|
||
"run" of sections worked out, but if you want me to also do sections on
|
||
other areas of coding, leave a message to Grant Smith in private E-Mail,
|
||
or start a conversation here in this conference. I will do a bit of
|
||
moderating of a sort, and point out things that have been done wrong.
|
||
|
||
In this, the first part, I will show you how you are supposed to set up
|
||
your Pascal program, how to get into 320x200x256 graphics mode without a
|
||
BGI file, and various methods of putpixels and a clearscreen utility.
|
||
|
||
NOTE : I drop source code all through my explanations. You needn't try
|
||
to grab all of it from all over the place, at the end of each part I
|
||
add a little program that uses all the new routines that we have
|
||
learned. If you do not fully understand a section, leave me
|
||
private mail telling me what you don't understand or asking how I
|
||
got something etc, and I will try to make myself clearer. One
|
||
last thing : When you spot a mistake I have made in one of my
|
||
parts, leave me mail and I will correct it post-haste.
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Disclaimer
|
||
|
||
|
||
|
||
Hi again, sorry that I have to add this, but here goes. All source code
|
||
obtained from this series of instruction programs is used at your own
|
||
risk. Denthor and the ASPHYXIA demo team hold no responsibility for any
|
||
loss or damage suffered by anyone through the use of this code. Look
|
||
guys, the code I'm going to give you has been used by us before in
|
||
Demos, Applications etc, and we have never had any compliants of machine
|
||
damage, but if something does go wrong with your computer, don't blame
|
||
us. Sorry, but that's the way it is.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ The MCGA mode and how you get into it in Pascal without a BGI
|
||
|
||
|
||
Lets face it. BGI's are next to worthless for demo coding. It is
|
||
difficult to find something that is slower then the BGI units for doing
|
||
graphics. Another thing is, they wern't really meant for 256 color
|
||
screens anyhow. You have to obtain a specific external 256VGA BGI to get
|
||
into it in Pascal, and it just doesn't make the grade.
|
||
|
||
So the question remains, how do we get into MCGA 320x200x256 mode in
|
||
Pascal without a BGI? The answer is simple : Assembly language.
|
||
Obviously assembly language has loads of functions to handle the VGA
|
||
card, and this is just one of them. If you look in Norton Gides to
|
||
Assembly Language, it says this ...
|
||
|
||
____________________________________________________________________
|
||
INT 10h, 00h (0) Set Video Mode
|
||
|
||
Sets the video mode.
|
||
|
||
On entry: AH 00h
|
||
AL Video mode
|
||
|
||
Returns: None
|
||
|
||
Registers destroyed: AX, SP, BP, SI, DI
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||
|
||
This is all well and good, but what does it mean? It means that if you
|
||
plug in the video mode into AL and call interrupt 10h, SHAZAM! you are
|
||
in the mode of your choice. Now, the MCGA video mode is mode 13h, and
|
||
here is how we do it in Pascal.
|
||
|
||
Procedure SetMCGA;
|
||
BEGIN
|
||
asm
|
||
mov ax,0013h
|
||
int 10h
|
||
end;
|
||
END;
|
||
|
||
There you have it! One call to that procedure, and BANG you are in
|
||
320x200x256 mode. We can't actually do anything in it yet, so to go back
|
||
to text mode, you make the video mode equal to 03h, as seen below :
|
||
|
||
Procedure SetText;
|
||
BEGIN
|
||
asm
|
||
mov ax,0003h
|
||
int 10h
|
||
end;
|
||
END;
|
||
|
||
|
||
BANG! We are back in text mode! Now, cry all your enquiring minds, what
|
||
use is this? We can get into the mode, but how do we actually SHOW
|
||
something on the screen? For that, you must move onto the next section
|
||
....
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Clearing the screen to a specific color
|
||
|
||
Now that we are in MCGA mode, how do we clear the screen. The answer is
|
||
simple : you must just remember that the base adress of the screen is
|
||
$a000. From $a000, the next 64000 bytes are what is actually displayed on
|
||
the screen (Note : 320 * 200 = 64000). So to clear the screen, you just use
|
||
the fillchar command (a basic Pascal command) like so :
|
||
|
||
FillChar (Mem [$a000:0],64000,Col);
|
||
|
||
What the mem command passes the Segment base and the Offset of a part of
|
||
memory : in this case the screen base is the Segment, and we are starting
|
||
at the top of the screen; Offset 0. The 64000 is the size of the screen
|
||
(see above), and Col is a value between 0 and 255, which represents the
|
||
color you want to clear the screen to.
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Putting a pixel on the screen (two different methoods)
|
||
|
||
If you look in Norton Guides about putting a pixel onto the screen, you
|
||
will see this :
|
||
|
||
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||
Writes a pixel dot of a specified color at a specified screen
|
||
coordinate.
|
||
|
||
On entry: AH 0Ch
|
||
AL Pixel color
|
||
CX Horizontal position of pixel
|
||
DX Vertical position of pixel
|
||
BH Display page number (graphics modes with more
|
||
than 1 page)
|
||
|
||
Returns: None
|
||
|
||
Registers destroyed: AX, SP, BP, SI, DI
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||
|
||
As seen from our SetMCGA example, you would write this by doing the following:
|
||
|
||
Procedure INTPutpixel (X,Y : Integer; Col : Byte);
|
||
BEGIN
|
||
asm
|
||
mov ah,0Ch
|
||
mov al,[col]
|
||
mov cx,[x]
|
||
mov dx,[y]
|
||
mov bx,[1]
|
||
int 10h
|
||
end;
|
||
END;
|
||
|
||
The X would be the X-Coordinate, the Y would be the Y-Coordinate, and the Col
|
||
would be the color of the pixel to place. Note that MCGA has 256 colors,
|
||
numbered 0 to 255. The startoff pallette is pretty grotty, and I will show
|
||
you how to alter it in my next lesson, but for now you will have to hunt for
|
||
colors that fit in for what you want to do. Luckily, a byte is 0 to 255, so
|
||
that is what we pass to the col variable. Have a look at the following.
|
||
|
||
CGA = 4 colours.
|
||
4x4 = 16
|
||
EGA = 16 colors.
|
||
16x16 = 256
|
||
VGA = 256 colors.
|
||
Therefore an EGA is a CGA squared, and a VGA is an EGA squared ;-)
|
||
|
||
Anyway, back to reality. Even though the abouve procedure is written in
|
||
assembly language, it is slooow. Why? I hear your enquiring minds cry. The
|
||
reason is simple : It uses interrupts (It calls INT 10h). Interrupts are
|
||
sloooow ... which is okay for getting into MCGA mode, but not for trying
|
||
to put down a pixel lickety-split. So, why not try the following ...
|
||
|
||
Procedure MEMPutpixel (X,Y : Integer; Col : Byte);
|
||
BEGIN
|
||
Mem [VGA:X+(Y*320)]:=Col;
|
||
END;
|
||
|
||
|
||
The Mem command, as we have seen above, allows you to point at a certain
|
||
point in memory ... the starting point is $a000, the base of the VGA's
|
||
memory, and then we specify how far into this base memory we start.
|
||
Think of the monitor this way. It starts in the top left hand corner at
|
||
0. As you increase the number, you start to move across the screen to your
|
||
right, until you reach 320. At 320, you have gone all the way across the
|
||
screen and come back out the left side, one pixel down. This carries on
|
||
until you reach 63999, at the bottom right hand side of the screen. This
|
||
is how we get the equation X+(Y*320). For every increased Y, we must
|
||
increment the number by 320. Once we are at the beginning of the Y line
|
||
we want, we add our X by how far out we want to be. This gives us the
|
||
exact point in memory that we want to be at, and then we set it equal to
|
||
the pixel value we want.
|
||
|
||
The MEM methood of putpixel is much faster, and it is shown in the sample
|
||
program at the end of this lesson. The ASPHYXIA team uses neither putpixel;
|
||
we use a DMA-Straight-To-Screen-Kill-Yer-Momma-With-An-Axe type putipixel
|
||
which is FAST. We will give it out, but only to those of you who show us
|
||
you are serious about coding. If you do do anything, upload it to me,
|
||
I will be very interested to see it. Remember : If you do glean anything
|
||
from these training sessions, give us a mention in your demos and UPLOAD
|
||
YOUR DEMO TO US!
|
||
|
||
Well, after this is the sample program; have fun with it, UNDERSTAND it,
|
||
and next week I will start on fun with the pallette.
|
||
|
||
See you all later,
|
||
- Denthor
|
||
|
||
|
||
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 2 ]==--
|
||
|
||
|
||
|
||
þ Introduction
|
||
|
||
|
||
|
||
Hi there again! This is Grant Smith, AKA Denthor of ASPHYXIA. This is the
|
||
second part of my Training Program for new programmers. I have only had a
|
||
lukewarm response to my first part of the trainer series ... remember, if
|
||
I don't hear from you, I will assume that you are all dead and will stop
|
||
writing the series ;-). Also, if you do get in contact with me I will give
|
||
you some of our fast assembly routines which will speed up your demos no
|
||
end. So go on, leave mail to GRANT SMITH in the main section of the
|
||
MailBox BBS, start up a discussion or ask a few questions in this Conference,
|
||
leave mail to ASPHYXIA on the ASPHYXIA BBS, leave mail to Denthor on
|
||
Connectix, or write to Grant Smith,
|
||
P.O.Box 270
|
||
Kloof
|
||
3640
|
||
See, there are many ways you can get in contact with me! Use one of them!
|
||
|
||
In this part, I will put the Pallette through it's paces. What the hell is
|
||
a pallette? How do I find out what it is? How do I set it? How do I stop
|
||
the "fuzz" that appears on the screen when I change the pallette? How do
|
||
I black out the screen using the pallette? How do I fade in a screen?
|
||
How do I fade out a screen? Why are telephone calls so expensive?
|
||
Most of these quesions will be answered in this, the second part of my
|
||
Trainer Series for Pascal.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is the Pallette?
|
||
|
||
A few weeks ago a friend of mine was playing a computer game. In the game
|
||
there was a machine with stripes of blue running across it. When the
|
||
machine was activated, while half of the the blue stripes stayed the same,
|
||
the other half started to change color and glow. He asked me how two stripes
|
||
of the same color suddenly become different like that. The answer is simple:
|
||
the program was changing the pallette. As you know from Part 1, there are
|
||
256 colors in MCGA mode, numbered 0 to 255. What you don't know is that each
|
||
if those colors is made up of different intensities of Red, Green and Blue,
|
||
the primary colors (you should have learned about the primary colors at
|
||
school). These intensities are numbers between 0 and 63. The color of
|
||
bright red would for example be obtained by setting red intensity to 63,
|
||
green intensity to 0, and blue intensity to 0. This means that two colors
|
||
can look exactly the same, eg you can set color 10 to bright red and color
|
||
78 to color bright red. If you draw a picture using both of those colors,
|
||
no-one will be able to tell the difference between the two.. It is only
|
||
when you again change the pallette of either of them will they be able to
|
||
tell the difference. Also, by changing the whole pallette, you can obtain
|
||
the "Fade in" and "Fade out" effects found in many demos and games.
|
||
Pallette manipulation can become quite confusing to some people, because
|
||
colors that look the same are in fact totally seperate.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do I read in the pallette value of a color?
|
||
|
||
This is very easy to do. To read in the pallette value, you enter in the
|
||
number of the color you want into port $3c7, then read in the values of
|
||
red, green and blue respectively from port $3c9. Simple, huh? Here is a
|
||
procedure that does it for you :
|
||
|
||
Procedure GetPal(ColorNo : Byte; Var R,G,B : Byte);
|
||
{ This reads the values of the Red, Green and Blue values of a certain
|
||
color and returns them to you. }
|
||
Begin
|
||
Port[$3c7] := ColorNo;
|
||
R := Port[$3c9];
|
||
G := Port[$3c9];
|
||
B := Port[$3c9];
|
||
End;
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do I set the pallette value of a color?
|
||
|
||
This is also as easy as 3.1415926535897932385. What you do is you enter in
|
||
the number of the color you want to change into port $3c8, then enter the
|
||
values of red, green and blue respectively into port $3c9. Because you are
|
||
all so lazy I have written the procedure for you ;-)
|
||
|
||
|
||
Procedure Pal(ColorNo : Byte; R,G,B : Byte);
|
||
{ This sets the Red, Green and Blue values of a certain color }
|
||
Begin
|
||
Port[$3c8] := ColorNo;
|
||
Port[$3c9] := R;
|
||
Port[$3c9] := G;
|
||
Port[$3c9] := B;
|
||
End;
|
||
|
||
|
||
Asphyxia doesn't use the above pallete procedures, we use assembler versions,
|
||
which will be given to PEOPLE WHO RESPOND TO THIS TRAINER SERIES (HINT,
|
||
HINT)
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do I stop the "fuzz" that appears on my screen when I change the
|
||
pallette?
|
||
|
||
If you have used the pallette before, you will have noticed that there is
|
||
quite a bit of "fuzz" on the screen when you change it. The way we counter
|
||
this is as follows : There is an elctron beam on your monitor that is
|
||
constantly updating your screen from top to bottom. As it gets to the
|
||
bottom of the screen, it takes a while for it to get back up to the top of
|
||
the screen to start updating the screen again. The period where it moves
|
||
from the bottom to the top is called the Verticle Retrace. During the
|
||
verticle retrace you may change the pallette without affecting what is
|
||
on the screen. What we do is that we wait until a verticle retrace has
|
||
started by calling a certain procedure; this means that everything we do
|
||
now will only be shown after the verticle retrace, so we can do all sorts
|
||
of strange and unusual things to the screen during this retrace and only
|
||
the results will be shown when the retrace is finished. This is way cool,
|
||
as it means that when we change the pallette, the fuzz doesn't appear on
|
||
the screen, only the result (the changed pallette), is seen after the
|
||
retrace! Neat, huh? ;-) I have put the purely assembler WaitRetrace routine
|
||
in the sample code that follows this message. Use it wisely, my son.
|
||
|
||
NOTE : WaitRetrace can be a great help to your coding ... code that fits
|
||
into one retrace will mean that the demo will run at the same
|
||
speed no matter what your computer speed (unless you are doing a lot
|
||
during the WaitRetrace and the computer is slooooow). Note that in
|
||
the following sample program and in our SilkyDemo, the thing will run
|
||
at the same speed whether turbo is on or off.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do I black out the screen using the pallette?
|
||
|
||
This is basic : just set the Red, Green and Blue values of all colors to
|
||
zero intensity, like so :
|
||
|
||
Procedure Blackout;
|
||
{ This procedure blackens the screen by setting the pallette values of
|
||
all the colors to zero. }
|
||
VAR loop1:integer;
|
||
BEGIN
|
||
WaitRetrace;
|
||
For loop1:=0 to 255 do
|
||
Pal (loop1,0,0,0);
|
||
END;
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do I fade in a screen?
|
||
|
||
Okay, this can be VERY effective. What you must first do is grab the
|
||
pallette into a variable, like so :
|
||
|
||
VAR Pall := Array [0.255,1..3] of BYTE;
|
||
|
||
0 to 255 is for the 256 colors in MCGA mode, 1 to 3 is red, green and blue
|
||
intensity values;
|
||
|
||
Procedure GrabPallette;
|
||
VAR loop1:integer;
|
||
BEGIN
|
||
For loop1:=0 to 255 do
|
||
Getpal (loop1,pall[loop1,1],pall[loop1,2],pall[loop1,3]);
|
||
END;
|
||
|
||
This loads the entire pallette into variable pall. Then you must blackout
|
||
the screen (see above), and draw what you want to screen without the
|
||
construction being shown. Then what you do is go throgh the pallette. For
|
||
each color, you see if the individual intensities are what they should be.
|
||
If not, you increase them by one unit until they are. Beacuse intensites
|
||
are in a range from 0 to 63, you only need do this a maximum of 64 times.
|
||
|
||
Procedure Fadeup;
|
||
VAR loop1,loop2:integer;
|
||
Tmp : Array [1..3] of byte;
|
||
{ This is temporary storage for the values of a color }
|
||
BEGIN
|
||
For loop1:=1 to 64 do BEGIN
|
||
{ A color value for Red, green or blue is 0 to 63, so this loop only
|
||
need be executed a maximum of 64 times }
|
||
WaitRetrace;
|
||
For loop2:=0 to 255 do BEGIN
|
||
Getpal (loop2,Tmp[1],Tmp[2],Tmp[3]);
|
||
If Tmp[1]<Pall[loop2,1] then inc (Tmp[1]);
|
||
If Tmp[2]<Pall[loop2,2] then inc (Tmp[2]);
|
||
If Tmp[3]<Pall[loop2,3] then inc (Tmp[3]);
|
||
{ If the Red, Green or Blue values of color loop2 are less then they
|
||
should be, increase them by one. }
|
||
Pal (loop2,Tmp[1],Tmp[2],Tmp[3]);
|
||
{ Set the new, altered pallette color. }
|
||
END;
|
||
END;
|
||
END;
|
||
|
||
Hey-presto! The screen fades up. You can just add in a delay before the
|
||
waitretrace if you feel it is too fast. Cool, no?
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do I fade out a screen?
|
||
|
||
This is just like the fade in of a screen, just in the opposite direction.
|
||
What you do is you check each color intensity. If it is not yet zero, you
|
||
decrease it by one until it is. BAAASIIIC!
|
||
|
||
Procedure FadeDown;
|
||
VAR loop1,loop2:integer;
|
||
Tmp : Array [1..3] of byte;
|
||
{ This is temporary storage for the values of a color }
|
||
BEGIN
|
||
For loop1:=1 to 64 do BEGIN
|
||
WaitRetrace;
|
||
For loop2:=0 to 255 do BEGIN
|
||
Getpal (loop2,Tmp[1],Tmp[2],Tmp[3]);
|
||
If Tmp[1]>0 then dec (Tmp[1]);
|
||
If Tmp[2]>0 then dec (Tmp[2]);
|
||
If Tmp[3]>0 then dec (Tmp[3]);
|
||
{ If the Red, Green or Blue values of color loop2 are not yet zero,
|
||
then, decrease them by one. }
|
||
Pal (loop2,Tmp[1],Tmp[2],Tmp[3]);
|
||
{ Set the new, altered pallette color. }
|
||
END;
|
||
END;
|
||
END;
|
||
|
||
Again, to slow the above down, put in a delay above the WaitRetrace. Fading
|
||
out the screen looks SO much more impressive then just clearing the screen;
|
||
it can make a world of difference in the impression your demo etc will
|
||
leave on the people viewing it. To restore the pallette, just do this :
|
||
|
||
Procedure RestorePallette;
|
||
VAR loop1:integer;
|
||
BEGIN
|
||
WaitRetrace;
|
||
For loop1:=0 to 255 do
|
||
pal (loop1,Pall[loop1,1],Pall[loop1,2],Pall[loop1,3]);
|
||
END;
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
Well, there are most of those origional questions answered ;-) The following
|
||
sample program is quite big, so it might take you a while to get around it.
|
||
Persevere and thou shalt overcome. Pallette manipulation has been a thorn
|
||
in many coders sides for quite some time, yet hopefully I have shown you
|
||
all how amazingly simple it is once you have grasped the basics.
|
||
|
||
I need more feedback! In which direction would you like me to head? Is there
|
||
any particular section you would like more info on? Also, upload me your
|
||
demo's, however trivial they might seem. We really want to get in contact
|
||
with/help out new and old coders alike, but you have to leave us that message
|
||
telling us about yourself and what you have done or want to do.
|
||
|
||
IS THERE ANYBODY OUT THERE!?!
|
||
|
||
P.S. Our new demo should be out soon ... it is going to be GOOOD ... keep
|
||
an eye out for it.
|
||
|
||
[ And so she came across him, slumped over his keyboard
|
||
yet again . 'It's three in the morning' she whispered.
|
||
'Let's get you to bed'. He stirred, his face bathed in
|
||
the dull light of his monitor. He mutters something.
|
||
As she leans across him to disconnect the power, she
|
||
asks him; 'Was it worth it?'. His answer surprises her.
|
||
'No.' he says. In his caffiene-enduced haze, he smiles.
|
||
'But it sure is a great way to relax.' ]
|
||
- Grant Smith
|
||
Tue 13 July, 1993
|
||
2:23 am.
|
||
|
||
See you next week!
|
||
- Denthor
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 3 ]==--
|
||
|
||
|
||
|
||
þ Introduction
|
||
|
||
|
||
|
||
Greetings! This is the third part of the VGA Trainer series! Sorry it
|
||
took so long to get out, but I had a running battle with the traffic
|
||
department for three days to get my car registered, and then the MailBox
|
||
went down. Ahh, well, life stinks. Anyway, today will do some things
|
||
vital to most programs : Lines and circles.
|
||
|
||
Watch out for next week's part : Virtual screens. The easy way to
|
||
eliminate flicker, "doubled sprites", and subjecting the user to watch
|
||
you building your screen. Almost every ASPHYXIA demo has used a virtual
|
||
screen (with the exception of the SilkyDemo), so this is one to watch out
|
||
for. I will also show you how to put all of these loose procedures into
|
||
units.
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith in private mail here on
|
||
the Mailbox BBS.
|
||
2) Write a message here in the Programming conference here
|
||
on the Mailbox (Preferred if you have a general
|
||
programming query or problem others would benefit from)
|
||
3) Write to ASPHYXIA on the ASPHYXIA BBS.
|
||
4) Write to Denthor, Eze or Livewire on Connectix.
|
||
5) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
6) Call me (Grant Smith) at 73 2129 (leave a message if you
|
||
call during varsity)
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Circle Algorithim
|
||
|
||
You all know what a circle looks like. But how do you draw one on the
|
||
computer?
|
||
|
||
You probably know circles drawn with the degrees at these points :
|
||
|
||
0
|
||
ÜÛ|ÛÜ
|
||
ÛÛÛ|ÛÛÛ
|
||
270 ----+---- 90
|
||
ÛÛÛ|ÛÛÛ
|
||
ßÛ|Ûß
|
||
180
|
||
|
||
Sorry about my ASCI ;-) ... anyway, Pascal doesn't work that way ... it
|
||
works with radians instead of degrees. (You can convert radians to degrees,
|
||
but I'm not going to go into that now. Note though that in pascal, the
|
||
circle goes like this :
|
||
|
||
270
|
||
ÜÛ|ÛÜ
|
||
ÛÛÛ|ÛÛÛ
|
||
180 ----+---- 0
|
||
ÛÛÛ|ÛÛÛ
|
||
ßÛ|Ûß
|
||
90
|
||
|
||
|
||
Even so, we can still use the famous equations to draw our circle ...
|
||
(You derive the following by using the theorem of our good friend
|
||
Pythagoras)
|
||
Sin (deg) = Y/R
|
||
Cos (deg) = X/R
|
||
(This is standard 8(?) maths ... if you haven't reached that level yet,
|
||
take this to your dad, or if you get stuck leave me a message and I'll
|
||
do a bit of basic Trig with you. I aim to please ;-))
|
||
|
||
Where Y = your Y-coord
|
||
X = your X-coord
|
||
R = your radius (the size of your circle)
|
||
deg = the degree
|
||
|
||
To simplify matters, we rewrite the equation to get our X and Y values :
|
||
|
||
Y = R*Sin(deg)
|
||
X = R*Cos(deg)
|
||
|
||
This obviousy is perfect for us, because it gives us our X and Y co-ords
|
||
to put into our putpixel routine (see Part 1). Because the Sin and Cos
|
||
functions return a Real value, we use a round function to transform it
|
||
into an Integer.
|
||
|
||
Procedure Circle (oX,oY,rad:integer;Col:Byte);
|
||
VAR deg:real;
|
||
X,Y:integer;
|
||
BEGIN
|
||
deg:=0;
|
||
repeat
|
||
X:=round(rad*COS (deg));
|
||
Y:=round(rad*sin (deg));
|
||
putpixel (x+ox,y+oy,Col);
|
||
deg:=deg+0.005;
|
||
until (deg>6.4);
|
||
END;
|
||
|
||
In the above example, the smaller the amount that deg is increased by,
|
||
the closer the pixels in the circle will be, but the slower the procedure.
|
||
0.005 seem to be best for the 320x200 screen. NOTE : ASPHYXIA does not use
|
||
this particular circle algorithm, ours is in assembly language, but this
|
||
one should be fast enough for most. If it isn't, give us the stuff you are
|
||
using it for and we'll give you ours.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Line algorithms
|
||
|
||
There are many ways to draw a line on the computer. I will describe one
|
||
and give you two. (The second one you can figure out for yourselves; it
|
||
is based on the first one but is faster)
|
||
|
||
The first thing you need to do is pass what you want the line to look
|
||
like to your line procedure. What I have done is said that x1,y1 is the
|
||
first point on the screen, and x2,y2 is the second point. We also pass the
|
||
color to the procedure. (Remember the screens top left hand corner is (0,0);
|
||
see Part 1)
|
||
|
||
Ie. o (X1,Y1)
|
||
ooooooooo
|
||
ooooooooo
|
||
oooooooo (X2,Y2)
|
||
|
||
Again, sorry about my drawings ;-)
|
||
|
||
To find the length of the line, we say the following :
|
||
|
||
XLength = ABS (x1-x2)
|
||
YLength = ABS (y1-y2)
|
||
|
||
The ABS function means that whatever the result, it will give you an
|
||
absolute, or posotive, answer. At this stage I set a variable stating
|
||
wheter the difference between the two x's are negative, zero or posotive.
|
||
(I do the same for the y's) If the difference is zero, I just use a loop
|
||
keeping the two with the zero difference posotive, then exit.
|
||
|
||
If neither the x's or y's have a zero difference, I calculate the X and Y
|
||
slopes, using the following two equations :
|
||
|
||
Xslope = Xlength / Ylength
|
||
Yslope = Ylength / Xlength
|
||
|
||
As you can see, the slopes are real numbers.
|
||
NOTE : XSlope = 1 / YSlope
|
||
|
||
Now, there are two ways of drawing the lines :
|
||
|
||
X = XSlope * Y
|
||
Y = YSlope * X
|
||
|
||
The question is, which one to use? if you use the wrong one, your line
|
||
will look like this :
|
||
|
||
o
|
||
o
|
||
o
|
||
|
||
Instead of this :
|
||
|
||
ooo
|
||
ooo
|
||
ooo
|
||
|
||
Well, the solution is as follows :
|
||
|
||
*\``|``/*
|
||
***\|/***
|
||
----+----
|
||
***/|\***
|
||
*/``|``\*
|
||
|
||
If the slope angle is in the area of the stars (*) then use the first
|
||
equation, if it is in the other section (`) then use the second one.
|
||
What you do is you calculate the variable on the left hand side by
|
||
putting the variable on the right hand side in a loop and solving. Below
|
||
is our finished line routine :
|
||
|
||
Procedure Line (x1,y1,x2,y2:integer;col:byte);
|
||
VAR x,y,xlength,ylength,dx,dy:integer;
|
||
xslope,yslope:real;
|
||
BEGIN
|
||
xlength:=abs (x1-x2);
|
||
if (x1-x2)<0 then dx:=-1;
|
||
if (x1-x2)=0 then dx:=0;
|
||
if (x1-x2)>0 then dx:=+1;
|
||
ylength:=abs (y1-y2);
|
||
if (y1-y2)<0 then dy:=-1;
|
||
if (y1-y2)=0 then dy:=0;
|
||
if (y1-y2)>0 then dy:=+1;
|
||
if (dy=0) then BEGIN
|
||
if dx<0 then for x:=x1 to x2 do
|
||
putpixel (x,y1,col);
|
||
if dx>0 then for x:=x2 to x1 do
|
||
putpixel (x,y1,col);
|
||
exit;
|
||
END;
|
||
if (dx=0) then BEGIN
|
||
if dy<0 then for y:=y1 to y2 do
|
||
putpixel (x1,y,col);
|
||
if dy>0 then for y:=y2 to y1 do
|
||
putpixel (x1,y,col);
|
||
exit;
|
||
END;
|
||
xslope:=xlength/ylength;
|
||
yslope:=ylength/xlength;
|
||
if (yslope/xslope<1) and (yslope/xslope>-1) then BEGIN
|
||
if dx<0 then for x:=x1 to x2 do BEGIN
|
||
y:= round (yslope*x);
|
||
putpixel (x,y,col);
|
||
END;
|
||
if dx>0 then for x:=x2 to x1 do BEGIN
|
||
y:= round (yslope*x);
|
||
putpixel (x,y,col);
|
||
END;
|
||
END
|
||
ELSE
|
||
BEGIN
|
||
if dy<0 then for y:=y1 to y2 do BEGIN
|
||
x:= round (xslope*y);
|
||
putpixel (x,y,col);
|
||
END;
|
||
if dy>0 then for y:=y2 to y1 do BEGIN
|
||
x:= round (xslope*y);
|
||
putpixel (x,y,col);
|
||
END;
|
||
END;
|
||
END;
|
||
|
||
Quite big, isn't it? Here is a much shorter way of doing much the same
|
||
thing :
|
||
|
||
function sgn(a:real):integer;
|
||
begin
|
||
if a>0 then sgn:=+1;
|
||
if a<0 then sgn:=-1;
|
||
if a=0 then sgn:=0;
|
||
end;
|
||
|
||
procedure line(a,b,c,d,col:integer);
|
||
var u,s,v,d1x,d1y,d2x,d2y,m,n:real;
|
||
i:integer;
|
||
begin
|
||
u:= c - a;
|
||
v:= d - b;
|
||
d1x:= SGN(u);
|
||
d1y:= SGN(v);
|
||
d2x:= SGN(u);
|
||
d2y:= 0;
|
||
m:= ABS(u);
|
||
n := ABS(v);
|
||
IF NOT (M>N) then
|
||
BEGIN
|
||
d2x := 0 ;
|
||
d2y := SGN(v);
|
||
m := ABS(v);
|
||
n := ABS(u);
|
||
END;
|
||
s := INT(m / 2);
|
||
FOR i := 0 TO round(m) DO
|
||
BEGIN
|
||
putpixel(a,b,col);
|
||
s := s + n;
|
||
IF not (s<m) THEN
|
||
BEGIN
|
||
s := s - m;
|
||
a:= a +round(d1x);
|
||
b := b + round(d1y);
|
||
END
|
||
ELSE
|
||
BEGIN
|
||
a := a + round(d2x);
|
||
b := b + round(d2y);
|
||
END;
|
||
end;
|
||
END;
|
||
|
||
This routine is very fast, and should meet almost all of your requirements
|
||
(ASPHYXIA used it for quite a while before we made our new one.)
|
||
In the end program, both the new line routine and the circle routine are
|
||
tested. A few of the procedures of the first parts are also used.
|
||
|
||
Line and circle routines may seem like fairly trivial things, but they are
|
||
a vital component of many programs, and you may like to look up other
|
||
methods of drawing them in books in the library (I know that here at the
|
||
varsity they have books for doing this kind of stuff all over the place)
|
||
A good line routine to look out for is the Bressenhams line routine ...
|
||
there is a Bressenhams circle routine too ... I have documentaiton for them
|
||
if anybody is interested, they are by far some of the fastest routines
|
||
you will use.
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
Varsity has started again, so I am (shock) going to bed before three in
|
||
the morning, so my quote this week wasn't written in the same wasted way
|
||
my last weeks one was (For last week's one, I had gotten 8 hours sleep in
|
||
3 days, and thought up and wrote the quote at 2:23 am before I fell asleep.)
|
||
|
||
[ "What does it do?" she asks.
|
||
"It's a computer," he replies.
|
||
"Yes, dear, but what does it do?"
|
||
"It ..er.. computes! It's a computer."
|
||
"What does it compute?"
|
||
"What? Er? Um. Numbers! Yes, numbers!" He smiles
|
||
worriedly.
|
||
"Why?"
|
||
"Why? Well ..um.. why?" He starts to sweat.
|
||
"I mean, is it just something to dust around, or does
|
||
it actually do something useful?"
|
||
"Um...you can call other computers with it!" Hope lights
|
||
up his eyes. "So you can get programs from other computers!"
|
||
"I see. Tell me, what do these programs do?"
|
||
"Do? I don't think I fol..."
|
||
"I see. They compute. Numbers. For no particular reason." He
|
||
withers under her gaze.
|
||
"Yes, but..."
|
||
She smiles, and he trails off, defeated. She takes another look
|
||
at the thing. "Although," she says, with a strange look in
|
||
her eyes. He looks up, an insane look of hope on his
|
||
face. "Does it come in pink?" she asks.
|
||
]
|
||
- Grant Smith
|
||
Tue 27 July, 1993
|
||
9:35 pm.
|
||
|
||
See you next time,
|
||
- Denthor
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 4 ]==--
|
||
|
||
|
||
|
||
þ Introduction
|
||
|
||
|
||
Howdy all! Welcome to the fourth part of this trainer series! It's a
|
||
little late, but I am sure you will find that the wait was worth it,
|
||
becase today I am going to show you how to use a very powerful tool :
|
||
Virtual Screens.
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith in private mail here on
|
||
the Mailbox BBS.
|
||
2) Write a message here in the Programming conference here
|
||
on the Mailbox (Preferred if you have a general
|
||
programming query or problem others would benefit from)
|
||
3) Write to ASPHYXIA on the ASPHYXIA BBS.
|
||
4) Write to Denthor, Eze or Livewire on Connectix.
|
||
5) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
6) Call me (Grant Smith) at 73 2129 (leave a message if you
|
||
call during varsity)
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is a Virtual Screen and why do we need it?
|
||
|
||
Let us say you are generating a complex screen numerous times on the fly
|
||
(for example scrolling up the screen then redrawing all the sprites for
|
||
each frame of a game you are writing.) Do you have any idea how awful it
|
||
would look if the user could actually see you erasing and redrawing each
|
||
sprite for each frame? Can you visualise the flicker effect this would
|
||
give off? Do you realise that there would be a "sprite doubling" effect
|
||
(where you see two copies of the same sprite next to each other)? In the
|
||
sample program I have included a part where I do not use virtual screens
|
||
to demonstrate these problems. Virtual screens are not the only way to
|
||
solve these problems, but they are definately the easiest to code in.
|
||
|
||
A virtual screen is this : a section of memory set aside that is exactly
|
||
like the VGA screen on which you do all your working, then "flip" it
|
||
on to your true screen. In EGA 640x350x16 you automatically have a
|
||
virtual page, and it is possible to have up to four on the MCGA using a
|
||
particular tweaked mode, but for our puposes we will set one up using base
|
||
memory.
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Setting up a virtual screen
|
||
|
||
As you will have seen in the first part of this trainer series, the MCGA
|
||
screen is 64000 bytes big (320x200=64000). You may also have noticed that
|
||
in TP 6.0 you arn't allowed too much space for normal variables. For
|
||
example, saying :
|
||
|
||
VAR Virtual : Array [1..64000] of byte;
|
||
|
||
would be a no-no, as you wouldn't have any space for your other variables.
|
||
What is the solution? I hear you enquiring minds cry. The answer : pointers!
|
||
Pointers to not use up the base 64k allocated to you by TP 6.0, it gets
|
||
space from somewhere else in the base 640k memory of your computer. Here is
|
||
how you set them up :
|
||
|
||
Type Virtual = Array [1..64000] of byte; { The size of our Virtual Screen }
|
||
VirtPtr = ^Virtual; { Pointer to the virtual screen }
|
||
|
||
VAR Virscr : VirtPtr; { Our first Virtual screen }
|
||
Vaddr : word; { The segment of our virtual screen}
|
||
|
||
If you put this in a program as it stands, and try to acess VirScr, your
|
||
machine will probably crash. Why? Because you have to get the memory for
|
||
your pointers before you can acess them! You do that as follows :
|
||
|
||
Procedure SetUpVirtual;
|
||
BEGIN
|
||
GetMem (VirScr,64000);
|
||
vaddr := seg (virscr^);
|
||
END;
|
||
|
||
This procedure has got the memory for the screen, then set vaddr to the
|
||
screens segment. DON'T EVER LEAVE THIS PROCEDURE OUT OF YOUR PROGRAM!
|
||
If you leave it out, when you write to your virtual screen you will probably
|
||
be writing over DOS or some such thing. Not a good plan ;-).
|
||
|
||
When you have finished your program, you will want to free the memory
|
||
taken up by the virtual screen by doing the following :
|
||
|
||
Procedure ShutDown;
|
||
BEGIN
|
||
FreeMem (VirScr,64000);
|
||
END;
|
||
|
||
If you don't do this your other programs will have less memory to use for
|
||
themselves.
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Putting a pixel to your virtual screen
|
||
|
||
This is very similar to putting a pixel to your normal MCGA screen, as
|
||
discussed in part one... here is our origonal putpixel :
|
||
|
||
Procedure PutPixel (X,Y : Integer; Col : Byte);
|
||
BEGIN
|
||
Mem [VGA:X+(Y*320)]:=col;
|
||
END;
|
||
|
||
For our virtual screen, we do the following :
|
||
|
||
Procedure VirtPutPixel (X,Y : Integer; Col : Byte);
|
||
BEGIN
|
||
Mem [Vaddr:X+(Y*320)]:=col;
|
||
END;
|
||
|
||
It seems quite wasteful to have two procedures doing exactly the same thing,
|
||
just to different screens, doesn't it? So why don't we combine the two like
|
||
this :
|
||
|
||
Procedure PutPixel (X,Y : Integer; Col : Byte; Where : Word);
|
||
BEGIN
|
||
Mem [Where:X+(Y*320)]:=col;
|
||
END;
|
||
|
||
To use this, you will say something like :
|
||
|
||
Putpixel (20,20,32,VGA);
|
||
PutPixel (30,30,64,Vaddr);
|
||
|
||
These two statements draw two pixels ... one to the VGA screen and one to
|
||
the virtual screen! Doesn't that make you jump with joy! ;-) You will
|
||
have noticed that we still can't actually SEE the virtual screen, so on to
|
||
the next part ...
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How to "Flip" your virtual screen on to the true screen
|
||
|
||
You in fact already have to tools to do this yourselves from information
|
||
in the previous parts of this trainer series. We will of course use the
|
||
Move command, like so :
|
||
|
||
Move (Virscr^,mem [VGA:0],64000);
|
||
|
||
simple, eh? Yuo may want to wait for a verticle retrace (Part 2) before you
|
||
do that, as it may make the flip much smoother (and, alas, slower).
|
||
|
||
Note that most of our other procedures may be altered to support the
|
||
virtual screen, such as Cls etc. (see Part 1 of this series), using the
|
||
methoods described above (I have altered the CLS procedure in the sample
|
||
program given at the end of this Part.)
|
||
|
||
We of ASPHYXIA have used virtual screens in almost all of our demos.
|
||
Can you imagine how awful the SoftelDemo would have looked if you had to
|
||
watch us redrawing the moving background, text and vectorballs for EACH
|
||
FRAME? The flicker, doubling effects etc would have made it awful! So
|
||
we used a virtual screen, and are very pleased with the result.
|
||
Note, though, that to get the speed we needed to get the demo fast enough,
|
||
we wrote our sprites routines, flip routines, pallette routines etc. all
|
||
in assembly. The move command is very fast, but not as fast as ASM ;-)
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
I am writing this on the varsity computers in between lectures. I prefer
|
||
writing & coding between 6pm and 4am, but it isn't a good plan when
|
||
varsity is on ;-), so this is the first part of the trainer series ever
|
||
written before 9pm.
|
||
|
||
I have been asked to do a part on scrolling the screen, so that is
|
||
probably what I will do for next week. Also, ASPHYXIA will soon be putting
|
||
up a small demo with source on the local boards. It will use routines
|
||
that we have discussed in this series, and demonstrate how powerful these
|
||
routines can be if used in the correct manner.
|
||
|
||
Some projects for you to do :
|
||
1) Rewrite the flip statement so that you can say :
|
||
flip (Vaddr,VGA);
|
||
flip (VGA,Vaddr);
|
||
( This is how ASPHYXIAS one works )
|
||
|
||
2) Put most of the routines (putpixel, cls, pal etc.) into a unit,
|
||
so that you do not need to duplicate the procedures in each program
|
||
you write. If you need help, leave me mail.
|
||
|
||
|
||
See you next week
|
||
- Denthor
|
||
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 5 ]==--
|
||
|
||
|
||
|
||
þ Introduction
|
||
|
||
Hello! This is Denthor here with the 5 part of the ASPHYXIA VGA Trainer
|
||
Series : The Scrolling Saga. I have had many requests for information on
|
||
scrolling, so I decided to make it this weeks topic. Note that I do make
|
||
reference to my recently released program TEXTER5, which should be available
|
||
from wherever you get this message. (Note to Sysops : If you put the trainer
|
||
series up on your boards, please add WORMIE.ZIP and TEXTER5.ZIP as they
|
||
both suppliment this series)
|
||
|
||
By the way, sorry for the delay in the appearance of this part. Tests,
|
||
projects and a few wild days of sin at the Wild Coast all conspired
|
||
against the prompt appearance of this part. Also note I need more input as
|
||
to what I should do future parts on, so leave me mail.
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith in private mail here on
|
||
the Mailbox BBS.
|
||
2) Write a message here in the Programming conference here
|
||
on the Mailbox (Preferred if you have a general
|
||
programming query or problem others would benefit from)
|
||
3) Write to ASPHYXIA on the ASPHYXIA BBS.
|
||
4) Write to Denthor, Eze or Livewire on Connectix.
|
||
5) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
6) Call me (Grant Smith) at 73 2129 (leave a message if you
|
||
call during varsity)
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is scrolling?
|
||
|
||
If you have ever seen a demo, you have probably seen some form of scrolling.
|
||
Our SILKYDEMO has quite a nice example of scrolling. What it is is a long
|
||
row of text moving across your screen, usually from right to left, eg :
|
||
|
||
H : Step 1
|
||
He : Step 2
|
||
Hel : Step 3
|
||
Hell : Step 4
|
||
Hello : Step 5
|
||
Hello : Step 6
|
||
|
||
etc. etc. See the program attatched for an example of scrolling.
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What do we scroll?
|
||
|
||
Usually, letters. Most groups put greetings and information in their
|
||
'scrollies', as they are termed. You can also scroll and entire screen
|
||
using the scrolling technique. Scrolling your text is a hell of a lot
|
||
less boring then just having it appear on your screen. Unfortunately,
|
||
'scrollies' have been used so many times in demos they are wearing a
|
||
bit thin, so usually they are accompanied by a cool picture or some nice
|
||
routine happening at the same time (In our SILKYDEMO we had a moving
|
||
checkerboard and colour bars going at the same time).
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do we scroll from side to side?
|
||
|
||
The theory behind scrolling is quite easy. Let us imagine that we are
|
||
scrolling a 16x16 font grabbed by TEXTER (;-)) across the top of the
|
||
screen (ie. 320 pixels) As we know, the VGA screen starts at zero at the
|
||
top left hand part of the screen, then counts up to the right to 319, then
|
||
goes back to the left hand side one pixel down at 320. (See Tut 1) This means
|
||
that a 16*320 scroller takes up the space 0 to 5119 on the screen. In ascii
|
||
this looks like this :
|
||
|
||
(0) . . (319)
|
||
(320) . . (639)
|
||
" " "
|
||
(4800) . . (5119)
|
||
|
||
Simple enough. Now what we do is we put down the first Y-line of the first
|
||
character onto the very right hand side of the screen , like so :
|
||
|
||
For loop1:=1 to 16 do
|
||
Putpixel (319,loop1-1,font['A',1,loop1],vga);
|
||
|
||
This will draw some stuff on the very right hand side. Your screen should now
|
||
look like this :
|
||
|
||
(0) . X. (319)
|
||
(320) . X. (639)
|
||
" " "
|
||
(4800) . X. (5119)
|
||
|
||
Next, we move each line one to the left, ie :
|
||
|
||
For loop1:=0 to 15 do
|
||
Move (mem[VGA:loop1*320+1],mem[VGA:loop1*320],320);
|
||
|
||
This scrolls the screen from right to left, which is the easiest to read.
|
||
To scroll the screen from left to right, swap the +1 onto the other side
|
||
of the command. Also, to increase the size of the portion scrolled, increase
|
||
the 15 to however many lines from the top you wish to scroll-1.
|
||
|
||
After this move, your screen will look like this :
|
||
|
||
(0) . X . (319)
|
||
(320) . X . (639)
|
||
" " "
|
||
(4800) . X . (5119)
|
||
^
|
||
Note this space
|
||
|
||
|
||
What you then do is draw in the next line on the right hand side, move it,
|
||
draw the next line, move it etc. etc. Tah-Dah! You have a scrolly! Fairly
|
||
simple, isn't it?
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do we scroll up or down?
|
||
|
||
To scroll up or down is also fairly simple. This can be used for 'movie
|
||
credit' endings (I once wrote a little game with a desert scrolling down
|
||
with you being a little robot on the bottom of the screen). The theory is
|
||
this : Draw the top line (or bottom line) then move the entire screen :
|
||
|
||
Move (mem[vga:0],mem[vga:320],63680);
|
||
{ 64000 - 320 = 63680 }
|
||
|
||
For scrolling down, or :
|
||
|
||
Move (mem[vga:320],mem[vga:0],63680);
|
||
|
||
For scrolling up. You then draw the next line and repeat.
|
||
|
||
Because of the simplicity of coding in a scrolly, most demos have one. It
|
||
is usually best to have something extra happening on the screen so that
|
||
the viewer doesn't get too bored, even, as I say, if it is only a really nice
|
||
picture.
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
The University of Natal, Durban, Science Dept., now has 10 new 486's!
|
||
This is a great boon, as now I can program nice routines during frees
|
||
(even though I am a Commerce Student (Shhhhh) ;-) ). I can now use those
|
||
previously wasted hours that I spent socialising and making friends
|
||
coding instead ;-)
|
||
|
||
I suggest you get a copy of TEXTER, for coding demos with fonts, or in fact
|
||
almost any graphics application, it is an amazing help, and we have used it
|
||
for *ALL* our demos. (P.S. We have written many demos, but many have been
|
||
written for companies and have not been released for the general public)
|
||
NOTE : For TEXTER's test program TEST.PAS, add {$X+} {$R-} if you have range
|
||
checking on (I code with it off.)
|
||
|
||
[ "I'm from the Computer Inspection Agency, sir,
|
||
I'm here to check your computer. Here is
|
||
my identification."
|
||
"Certainly. Have a look, I'm clean. I don't have
|
||
any pirated software."
|
||
The C-man pushes past him and sits in front of the
|
||
computer. He notes the fact that the computer
|
||
is currently off with a look of disdain. He
|
||
makes a note on his clipboard. He boots up.
|
||
"What is this?" he asks, pointing at the screen.
|
||
"It's MasterMenu" stutters the man. "I wrote it
|
||
myself!"
|
||
"Do you know what the penalty is for using junk
|
||
like this on a private machine?" The C-man smiles.
|
||
"This is a two-month sentance in itself!"
|
||
"I'm sorry sir! It won't happen again!"
|
||
"I know. I'll make sure of that." He smiles again.
|
||
The C-man runs through the hard drive, checking for
|
||
illeagal software, bad programs and anti-government
|
||
propaganda. He notes with satisfaction that he has
|
||
enough to put this weenie away for ten years, not that
|
||
it mattered. He usually could just make something up.
|
||
He comes to the last entry on the aphebetised menu tree.
|
||
His hands jerk away from the keyboard. Then, tentatively,
|
||
he types in the three letters of doom. He looks at the
|
||
man, who is backing away with wide eyes and his hands
|
||
outstretched in front of him, as if to ward off a blow.
|
||
The C-man smiles, his lips a thin, hard line.
|
||
"Windows!"
|
||
]
|
||
- Grant Smith
|
||
1:55pm
|
||
16/9/93
|
||
|
||
Cheers,
|
||
- Denthor
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 6 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hi there! I'm back, with the latest part in the series : Pregenerated
|
||
arrays. This is a fairly simple concept that can treble the speed of
|
||
your code, so have a look.
|
||
|
||
I still suggest that if you haven't got a copy of TEXTER that you get it.
|
||
This is shareware, written by me, that allows you to grab fonts and use
|
||
them in your own programs.
|
||
|
||
I downloaded the Friendly City BBS Demo, an intro for a PE BBS, written
|
||
by a new group called DamnRite, with coder Brett Step. The music was
|
||
excellent, written by Kon Wilms (If I'm not mistaken, he is an Amiga
|
||
weenie ;-)). A very nice first production, and I can't wait to see more
|
||
of their work. I will try con a local BBS to allow me to send Brett some
|
||
fido-mail.
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith in private mail here on
|
||
the Mailbox BBS.
|
||
2) Write a message here in the Programming conference here
|
||
on the Mailbox (Preferred if you have a general
|
||
programming query or problem others would benefit from)
|
||
3) Write to ASPHYXIA on the ASPHYXIA BBS.
|
||
4) Write to Denthor, Eze or Livewire on Connectix.
|
||
5) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity)
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Why do I need a lookup table? What is it?
|
||
|
||
A lookup table is an imaginary table in memory where you look up the
|
||
answers to certain mathematical equations instead of recalculating them
|
||
each time. This may speed things up considerably. Please note that a
|
||
lookup table is sometimes referred to as a pregenerated array.
|
||
|
||
One way of looking at a lookup table is as follows : Let us say that for
|
||
some obscure reason you need to calculate a lot of multiplications (eg.
|
||
5*5 , 7*4 , 9*2 etc.). Instead of actually doing a slow multiply each
|
||
time, you can generate a kind of bonds table, as seen below :
|
||
|
||
|
||
ÉÍÑÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍ»
|
||
ÇÄÅĶ 1 ³ 2 ³ 3 ³ 4 ³ 5 ³ 6 ³ 7 ³ 8 ³ 9 º
|
||
ÇÄÁÄ×ÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͵
|
||
º 1 º 1 ³ 2 ³ 3 ³ 4 ³ 5 ³ 6 ³ 7 ³ 8 ³ 9 ³
|
||
ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´
|
||
º 2 º 2 ³ 4 ³ 6 ³ 8 ³ 10 ³ 12 ³ 14 ³ 16 ³ 18 ³
|
||
ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´
|
||
º 3 º 3 ³ 6 ³ 9 ³ 12 ³ 15 ³ 18 ³ 21 ³ 24 ³ 27 ³
|
||
ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´
|
||
º 4 º 4 ³ 8 ³ 12 ³ 16 ³ 20 ³ 24 ³ 28 ³ 32 ³ 36 ³
|
||
ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´
|
||
º 5 º 5 ³ 10 ³ 15 ³ 20 ³ 25 ³ 30 ³ 35 ³ 40 ³ 45 ³
|
||
ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´
|
||
º 6 º 6 ³ 12 ³ 18 ³ 24 ³ 30 ³ 36 ³ 42 ³ 48 ³ 54 ³
|
||
ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´
|
||
º 7 º 7 ³ 14 ³ 21 ³ 28 ³ 35 ³ 42 ³ 49 ³ 56 ³ 63 ³
|
||
ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´
|
||
º 8 º 8 ³ 16 ³ 24 ³ 32 ³ 40 ³ 48 ³ 56 ³ 64 ³ 72 ³
|
||
ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´
|
||
º 9 º 9 ³ 18 ³ 27 ³ 36 ³ 45 ³ 54 ³ 63 ³ 72 ³ 81 ³
|
||
ÈÍÍÍÊÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ
|
||
|
||
This means that instead of calculating 9*4, you just find the 9 on the
|
||
top and the 4 on the side, and the resulting number is the answer. This
|
||
type of table is very useful when the equations are very long to do.
|
||
|
||
The example I am going to use for this part is that of circles. Cast
|
||
your minds back to Part 3 on lines and circles. The circle section took
|
||
quite a while to finish drawing, mainly because I had to calculate the
|
||
SIN and COS for EVERY SINGLE POINT. Calculating SIN and COS is obviously
|
||
very slow, and that was reflected in the speed of the section.
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do I generate a lookup table?
|
||
|
||
This is very simple. In my example, I am drawing a circle. A circle has
|
||
360 degrees, but for greater accuracy, to draw my circle I will start
|
||
with zero and increase my degrees by 0.4. This means that in each circle
|
||
there need to be 8000 SINs and COSes (360/0.4=8000). Putting these into
|
||
the base 64k that Pascal allocates for normal variables is obviously not
|
||
a happening thing, so we define them as pointers in the following
|
||
manner:
|
||
TYPE table = Array [1..8000] of real;
|
||
|
||
VAR sintbl : ^table;
|
||
costbl : ^table;
|
||
|
||
Then in the program we get the memory for these two pointers. Asphyxia
|
||
was originally thinking of calling itself Creative Reboot Inc., mainly
|
||
because we always forgot to get the necessary memory for our pointers.
|
||
(Though a bit of creative assembly coding also contributed to this. We
|
||
wound up rating our reboots on a scale of 1 to 10 ;-)). The next obvious
|
||
step is to place our necessary answers into our lookup tables. This can
|
||
take a bit of time, so in a demo, you would do it in the very beginning
|
||
(people just think it's slow disk access or something), or after you
|
||
have shown a picture (while the viewer is admiring it, you are
|
||
calculating pi to its 37th degree in the background ;-)) Another way of
|
||
doing it is, after calculating it once, you save it to a file which you
|
||
then load into the variable at the beginning of the program. Anyway,
|
||
this is how we will calculate the table for our circle :
|
||
|
||
Procedure Setup;
|
||
VAR deg:real;
|
||
BEGIN
|
||
deg:=0;
|
||
for loop1:=1 to 8000 do BEGIN
|
||
deg:=deg+0.4;
|
||
costbl^[loop1]:=cos (rad(deg));
|
||
sintbl^[loop1]:=sin (rad(deg));
|
||
END;
|
||
END;
|
||
|
||
This will calculate the needed 16000 reals and place them into our two
|
||
variables. The amount of time this takes is dependant on your computer.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do I use a lookup table?
|
||
|
||
This is very easy. In your program, wherever you put
|
||
cos (rad(deg)),
|
||
you just replace it with :
|
||
costbl^[deg]
|
||
|
||
Easy, no? Note that the new "deg" variable is now an integer, always
|
||
between 1 and 8000.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Where else do I use lookup tables?
|
||
|
||
Lookup tables may be used in many different ways. For example, when
|
||
working out 3-dimensional objects, sin and cos are needed often, and are
|
||
best put in a lookup table. In a game, you may pregen the course an
|
||
enemy may take when attacking. Even saving a picture (for example, a
|
||
plasma screen) after generating it, then loading it up later is a form
|
||
of pregeneration.
|
||
|
||
When you feel that your program is going much too slow, your problems
|
||
may be totally sorted out by using a table. Or, maybe not. ;-)
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
As you have seen above, lookup tables aren't all that exciting, but they
|
||
are useful and you need to know how to use them. The attached sample
|
||
program will demonstrate just how big a difference they can make.
|
||
|
||
Keep on coding, and if you finish anything, let me know about it! I
|
||
never get any mail, so all mail is greatly appreciated ;-)
|
||
|
||
Sorry, no quote today, it's hot and I'm tired. Maybe next time ;-)
|
||
|
||
- Denthor
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 7 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hello! By popular request, this part is all about animation. I will be
|
||
going over three methods of doing animation on a PC, and will
|
||
concerntrate specifically on one, which will be demonstrated in the
|
||
attached sample code.
|
||
|
||
Although not often used in demo coding, animation is usually used in
|
||
games coding, which can be almost as rewarding ;-)
|
||
|
||
In this part I will also be a lot less stingy with assembler code :)
|
||
Included will be a fairly fast pure assembler putpixel, an asm screen
|
||
flip command, an asm icon placer, an asm partial-flip and one or two
|
||
others. I will be explaining how these work in detail, so this may also
|
||
be used as a bit of an asm-trainer too.
|
||
|
||
By the way, I apologise for this part taking so long to be released, but
|
||
I only finished my exams a few days ago, and they of course took
|
||
preference ;-). I have also noticed that the MailBox BBS is no longer
|
||
operational, so the trainer will be uploaded regularly to the BBS lists
|
||
shown at the end of this tutorial.
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write a message in the Programming conference on the
|
||
For Your Eyes Only BBS (of which I am the Moderator )
|
||
This is preferred if you have a general programming query
|
||
or problem others would benefit from.
|
||
4) Write to Denthor, Eze or Livewire on Connectix.
|
||
5) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity)
|
||
7) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
|
||
mention the word Denthor near the top of the letter.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ The Principals of Animation
|
||
|
||
I am sure all of you have seen a computer game with animation at one or
|
||
other time. There are a few things that an animation sequence must do in
|
||
order to give an impression of realism. Firstly, it must move,
|
||
preferably using different frames to add to the realism (for example,
|
||
with a man walking you should have different frames with the arms an
|
||
legs in different positions). Secondly, it must not destroy the
|
||
background, but restore it after it has passed over it.
|
||
|
||
This sounds obvious enough, but can be very difficult to code when you
|
||
have no idea of how to go about achieving that.
|
||
|
||
In this trainer I will discuss various methods of meeting these two
|
||
objectives.
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Frames and Object Control
|
||
|
||
It is quite obvious that for most animation to succeed, you must have
|
||
numerous frames of the object in various poses (such as a man with
|
||
several frames of him walking). When shown one after the other, these
|
||
give the impression of natural movement.
|
||
|
||
So, how do we store these frames? I hear you cry. Well, the obvious
|
||
method is to store them in arrays. After drawing a frame in Autodesk
|
||
Animator and saving it as a .CEL, we usually use the following code to
|
||
load it in :
|
||
|
||
TYPE icon = Array [1..50,1..50] of byte;
|
||
|
||
VAR tree : icon;
|
||
|
||
Procedure LoadCEL (FileName : string; ScrPtr : pointer);
|
||
var
|
||
Fil : file;
|
||
Buf : array [1..1024] of byte;
|
||
BlocksRead, Count : word;
|
||
begin
|
||
assign (Fil, FileName);
|
||
reset (Fil, 1);
|
||
BlockRead (Fil, Buf, 800); { Read and ignore the 800 byte header }
|
||
Count := 0; BlocksRead := $FFFF;
|
||
while (not eof (Fil)) and (BlocksRead <> 0) do begin
|
||
BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
|
||
Count := Count + 1024;
|
||
end;
|
||
close (Fil);
|
||
end;
|
||
|
||
BEGIN
|
||
Loadcel ('Tree.CEL',addr (tree));
|
||
END.
|
||
|
||
We now have the 50x50 picture of TREE.CEL in our array tree. We may access
|
||
this array in the usual manner (eg. col:=tree [25,30]). If the frame is
|
||
large, or if you have many frames, try using pointers (see previous
|
||
parts)
|
||
|
||
Now that we have the picture, how do we control the object? What if we
|
||
want multiple trees wandering around doing their own thing? The solution
|
||
is to have a record of information for each tree. A typical data
|
||
structure may look like the following :
|
||
|
||
TYPE Treeinfo = Record
|
||
x,y:word; { Where the tree is }
|
||
speed:byte; { How fast the tree is moving }
|
||
Direction:byte; { Where the tree is facing }
|
||
frame:byte { Which animation frame the tree is
|
||
currently involved in }
|
||
active:boolean; { Is the tree actually supposed to be
|
||
shown/used? }
|
||
END;
|
||
|
||
VAR Forest : Array [1..20] of Treeinfo;
|
||
|
||
You now have 20 trees, each with their own information, location etc.
|
||
These are accessed using the following means :
|
||
Forest [15].x:=100;
|
||
This would set the 15th tree's x coordinate to 100.
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Restoring the Overwritten Background
|
||
|
||
I will discuss three methods of doing this. These are NOT NECESSARILY
|
||
THE ONLY OR BEST WAYS TO DO THIS! You must experiment and decide which
|
||
is the best for your particular type of program.
|
||
|
||
METHOD 1 :
|
||
|
||
Step 1 : Create two virtual pages, Vaddr and Vaddr2.
|
||
Step 2 : Draw the background to Vaddr2.
|
||
Step 3 : Flip Vaddr2 to Vaddr.
|
||
Step 4 : Draw all the foreground objects onto Vaddr.
|
||
Step 5 : Flip Vaddr to VGA.
|
||
Step 6 : Repeat from 3 continuously.
|
||
|
||
In ascii, it looks like follows ...
|
||
|
||
+---------+ +---------+ +---------+
|
||
| | | | | |
|
||
| VGA | <======= | VADDR | <====== | VADDR2 |
|
||
| | | (bckgnd)| | (bckgnd)|
|
||
| | |+(icons) | | |
|
||
+---------+ +---------+ +---------+
|
||
|
||
The advantages of this approach is that it is straightforward, continual
|
||
reading of the background is not needed, there is no flicker and it is
|
||
simple to implement. The disadvantages are that two 64000 byte virtual
|
||
screens are needed, and the procedure is not very fast because of the
|
||
slow speed of flipping.
|
||
|
||
|
||
METHOD 2 :
|
||
|
||
Step 1 : Draw background to VGA.
|
||
Step 2 : Grab portion of background that icon will be placed on.
|
||
Step 3 : Place icon.
|
||
Step 4 : Replace portion of background from Step 2 over icon.
|
||
Step 5 : Repeat from step 2 continuously.
|
||
|
||
In terms of ascii ...
|
||
|
||
+---------+
|
||
| +--|------- + Background restored (3)
|
||
| * -|------> * Background saved to memory (1)
|
||
| ^ |
|
||
| +--|------- # Icon placed (2)
|
||
+---------+
|
||
|
||
The advantages of this method is that very little extra memory is
|
||
needed. The disadvantages are that writing to VGA is slower then writing
|
||
to memory, and there may be large amounts of flicker.
|
||
|
||
|
||
METHOD 3 :
|
||
|
||
Step 1 : Set up one virtual screen, VADDR.
|
||
Step 2 : Draw background to VADDR.
|
||
Step 3 : Flip VADDR to VGA.
|
||
Step 4 : Draw icon to VGA.
|
||
Step 5 : Transfer background portion from VADDR to VGA.
|
||
Step 6 : Repeat from step 4 continuously.
|
||
|
||
In ascii ...
|
||
|
||
+---------+ +---------+
|
||
| | | |
|
||
| VGA | | VADDR |
|
||
| | | (bckgnd)|
|
||
| Icon>* <|-----------|--+ |
|
||
+---------+ +---------+
|
||
|
||
The advantages are that writing from the virtual screen is quicker then
|
||
from VGA, and there is less flicker then in Method 2. Disadvantages are
|
||
that you are using a 64000 byte virtual screen, and flickering occurs
|
||
with large numbers of objects.
|
||
|
||
In the attached sample program, a mixture of Method 3 and Method 1 is
|
||
used. It is faster then Method 1, and has no flicker, unlike Method 3.
|
||
What I do is I use VADDR2 for background, but only restore the
|
||
background that has been changed to VADDR, before flipping to VGA.
|
||
|
||
In the sample program, you will see that I restore the entire background
|
||
of each of the icons, and then place all the icons. This is because if I
|
||
replace the background then place the icon on each object individually,
|
||
if two objects are overlapping, one is partially overwritten.
|
||
|
||
The following sections are explanations of how the various assembler
|
||
routines work. This will probably be fairly boring for you if you
|
||
already know assembler, but should help beginners and dabblers alike.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ The ASM Putpixel
|
||
|
||
To begin with, I will explain a few of the ASM variables and functions :
|
||
|
||
<NOTE THAT THIS IS AN EXTREMELY SIMPLISTIC VIEW OF ASSEMBLY LANGUAGE!
|
||
There are numerous books to advance your knowledge, and the Norton
|
||
Guides assembler guide may be invaluable for people beginning to code
|
||
in assembler. I haven't given you the pretty pictures you are supposed
|
||
to have to help you understand it easier, I have merely laid it out like
|
||
a programming language with it's own special procedures. >
|
||
|
||
There are 4 register variables : AX,BX,CX,DX. These are words (double
|
||
bytes) with a range from 0 to 65535. You may access the high and low
|
||
bytes of these by replacing the X with a "H" for high or "L" for low.
|
||
For example, AL has a range from 0-255.
|
||
|
||
You also have two pointers : ES:DI and DS:SI. The part on the left is
|
||
the segment to which you are pointing (eg $a000), and the right hand
|
||
part is the offset, which is how far into the segment you are pointing.
|
||
Turbo Pascal places a variable over 16k into the base of a segment, ie.
|
||
DI or SI will be zero at the start of the variable.
|
||
|
||
If you wish to be pointing to pixel number 3000 on the VGA screen (see
|
||
previous parts for the layout of the VGA screen), ES would be equal to
|
||
$a000 and DI would be equal to 3000. You can quite as easily make ES or
|
||
DS be equal to the offset of a virtual screen.
|
||
|
||
Here are a few functions that you will need to know :
|
||
|
||
mov destination,source This moves the value in source to
|
||
destination. eg mov ax,50
|
||
add destination,source This adds source to destination,
|
||
the result being stored in destination
|
||
mul source This multiplies AX by source. If
|
||
source is a byte, the source is
|
||
multiplied by AL, the result being
|
||
stored in AX. If source is a word,
|
||
the source is multiplied by AX, the
|
||
result being stored in DX:AX
|
||
movsb This moves the byte that DS:SI is
|
||
pointing to into ES:DI, and
|
||
increments SI and DI.
|
||
movsw Same as movsb except it moves a
|
||
word instead of a byte.
|
||
stosw This moves AX into ES:DI. stosb
|
||
moves AL into ES:DI. DI is then
|
||
incremented.
|
||
push register This saves the value of register by
|
||
pushing it onto the stack. The
|
||
register may then be altered, but
|
||
will be restored to it's original
|
||
value when popped.
|
||
pop register This restores the value of a pushed
|
||
register. NOTE : Pushed values must
|
||
be popped in the SAME ORDER but
|
||
REVERSED.
|
||
rep command This repeats Command by as many
|
||
times as the value in CX
|
||
|
||
|
||
SHL Destination,count ;
|
||
and SHR Destination,count ;
|
||
need a bit more explaining. As you know, computers think in ones and
|
||
zeroes. Each number may be represented in this base 2 operation. A byte
|
||
consists of 8 ones and zeroes (bits), and have a range from 0 to 255. A
|
||
word consists of 16 ones and zeroes (bits), and has a range from 0 to
|
||
65535. A double word consists of 32 bits.
|
||
|
||
The number 53 may be represented as follows : 00110101. Ask someone who
|
||
looks clever to explain to you how to convert from binary to decimal and
|
||
vice-versa.
|
||
|
||
What happens if you shift everything to the left? Drop the leftmost
|
||
number and add a zero to the right? This is what happens :
|
||
|
||
00110101 = 53
|
||
<-----
|
||
01101010 = 106
|
||
|
||
As you can see, the value has doubled! In the same way, by shifting one
|
||
to the right, you halve the value! This is a VERY quick way of
|
||
multiplying or dividing by 2. (note that for dividing by shifting, we
|
||
get the trunc of the result ... ie. 15 shr 1 = 7)
|
||
|
||
In assembler the format is SHL destination,count This shifts
|
||
destination by as many bits in count (1=*2, 2=*4, 3=*8, 4=*16 etc)
|
||
Note that a shift takes only 2 clock cycles, while a mul can take up to 133
|
||
clock cycles. Quite a difference, no? Only 286es or above may have count
|
||
being greater then one.
|
||
|
||
This is why to do the following to calculate the screen coordinates for
|
||
a putpixel is very slow :
|
||
|
||
mov ax,[Y]
|
||
mov bx,320
|
||
mul bx
|
||
add ax,[X]
|
||
mov di,ax
|
||
|
||
But alas! I hear you cry. 320 is not a value you may shift by, as you
|
||
may only shift by 2,4,8,16,32,64,128,256,512 etc.etc. The solution is
|
||
very cunning. Watch.
|
||
|
||
mov bx,[X]
|
||
mov dx,[Y]
|
||
push bx
|
||
mov bx, dx {; bx = dx = Y}
|
||
mov dh, dl {; dh = dl = Y}
|
||
xor dl, dl {; These 2 lines equal dx*256 }
|
||
shl bx, 1
|
||
shl bx, 1
|
||
shl bx, 1
|
||
shl bx, 1
|
||
shl bx, 1
|
||
shl bx, 1 {; bx = bx * 64}
|
||
add dx, bx {; dx = dx + bx (ie y*320)}
|
||
pop bx {; get back our x}
|
||
add bx, dx {; finalise location}
|
||
mov di, bx
|
||
|
||
Let us have a look at this a bit closer shall we?
|
||
bx=dx=y dx=dx*256 ; bx=bx*64 ( Note, 256+64 = 320 )
|
||
|
||
dx+bx=Correct y value, just add X!
|
||
|
||
As you can see, in assembler, the shortest code is often not the
|
||
fastest.
|
||
|
||
The complete putpixel procedure is as follows :
|
||
|
||
Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
|
||
{ This puts a pixel on the screen by writing directly to memory. }
|
||
BEGIN
|
||
Asm
|
||
push ds {; Make sure these two go out the }
|
||
push es {; same they went in }
|
||
mov ax,[where]
|
||
mov es,ax {; Point to segment of screen }
|
||
mov bx,[X]
|
||
mov dx,[Y]
|
||
push bx {; and this again for later}
|
||
mov bx, dx {; bx = dx}
|
||
mov dh, dl {; dx = dx * 256}
|
||
xor dl, dl
|
||
shl bx, 1
|
||
shl bx, 1
|
||
shl bx, 1
|
||
shl bx, 1
|
||
shl bx, 1
|
||
shl bx, 1 {; bx = bx * 64}
|
||
add dx, bx {; dx = dx + bx (ie y*320)}
|
||
pop bx {; get back our x}
|
||
add bx, dx {; finalise location}
|
||
mov di, bx {; di = offset }
|
||
{; es:di = where to go}
|
||
xor al,al
|
||
mov ah, [Col]
|
||
mov es:[di],ah {; move the value in ah to screen
|
||
point es:[di] }
|
||
pop es
|
||
pop ds
|
||
End;
|
||
END;
|
||
|
||
Note that with DI and SI, when you use them :
|
||
mov di,50 Moves di to position 50
|
||
mov [di],50 Moves 50 into the place di is pointing to
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ The Flip Procedure
|
||
|
||
This is fairly straightforward. We get ES:DI to point to the start of
|
||
the destination screen, and DS:SI to point to the start of the source
|
||
screen, then do 32000 movsw (64000 bytes).
|
||
|
||
procedure flip(source,dest:Word);
|
||
{ This copies the entire screen at "source" to destination }
|
||
begin
|
||
asm
|
||
push ds
|
||
mov ax, [Dest]
|
||
mov es, ax { ES = Segment of source }
|
||
mov ax, [Source]
|
||
mov ds, ax { DS = Segment of source }
|
||
xor si, si { SI = 0 Faster then mov si,0 }
|
||
xor di, di { DI = 0 }
|
||
mov cx, 32000
|
||
rep movsw { Repeat movsw 32000 times }
|
||
pop ds
|
||
end;
|
||
end;
|
||
|
||
The cls procedure works in much the same way, only it moves the color
|
||
into AX then uses a rep stosw (see program for details)
|
||
|
||
The PAL command is almost exactly the same as it's Pascal equivalent
|
||
(see previous tutorials). Look in the sample code to see how it uses the
|
||
out and in commands.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In Closing
|
||
|
||
The assembler procedures presented to you in here are not at their best.
|
||
Most of these are procedures ASPHYXIA abandoned for better ones after
|
||
months of use. But, as you will soon see, they are all MUCH faster then
|
||
the original Pascal equivalents I originally gave you. In future, I
|
||
hope to give you more and more assembler procedures for your ever
|
||
growing collections. But, as you know, I am not always very prompt with
|
||
this series (I don't know if even one has been released within one week
|
||
of the previous one), so if you want to get any stuff done, try do it
|
||
yourself. What do you have to lose, aside from your temper and a few
|
||
rather inventive reboots ;-)
|
||
|
||
What should I do for the next trainer? A simple 3-d tutorial? You may
|
||
not like it, because I would go into minute detail of how it works :)
|
||
Leave me suggestions for future trainers by any of the means discussed
|
||
at the top of this trainer.
|
||
|
||
After the customary quote, I will place a listing of the BBSes I
|
||
currently know that regularly carry this Trainer Series. If your BBS
|
||
receives it regularly, no matter where in the country you are, get a
|
||
message to me and I'll add it to the list. Let's make it more convenient
|
||
for locals to grab a copy without calling long distance ;-)
|
||
|
||
[ There they sit, the preschooler class encircling their
|
||
mentor, the substitute teacher.
|
||
"Now class, today we will talk about what you want to be
|
||
when you grow up. Isn't that fun?" The teacher looks
|
||
around and spots the child, silent, apart from the others
|
||
and deep in thought. "Jonny, why don't you start?" she
|
||
encourages him.
|
||
Jonny looks around, confused, his train of thought
|
||
disrupted. He collects himself, and stares at the teacher
|
||
with a steady eye. "I want to code demos," he says,
|
||
his words becoming stronger and more confidant as he
|
||
speaks. "I want to write something that will change
|
||
peoples perception of reality. I want them to walk
|
||
away from the computer dazed, unsure of their footing
|
||
and eyesight. I want to write something that will
|
||
reach out of the screen and grab them, making
|
||
heartbeats and breathing slow to almost a halt. I want
|
||
to write something that, when it is finished, they
|
||
are reluctant to leave, knowing that nothing they
|
||
experience that day will be quite as real, as
|
||
insightful, as good. I want to write demos."
|
||
Silence. The class and the teacher stare at Jonny, stunned. It
|
||
is the teachers turn to be confused. Jonny blushes,
|
||
feeling that something more is required. "Either that
|
||
or I want to be a fireman."
|
||
]
|
||
- Grant Smith
|
||
14:32
|
||
21/11/93
|
||
|
||
See you next time,
|
||
- DENTHOR
|
||
|
||
These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º
|
||
ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º
|
||
ºConnectix BBS º(031) 266-9992 ºALL º * º * º * º
|
||
ºFor Your Eyes Only BBS º(031) 285-318 ºA/H º * º * º * º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ
|
||
|
||
Open = Open at all times or only A/H
|
||
Msg = Available in message base
|
||
File = Available in file base
|
||
Past = Previous Parts available
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 8 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hello everybody! Christmas is over, the last of the chocolates have been
|
||
eaten, so it's time to get on with this, the eighth part of the ASPHYXIA
|
||
Demo Trainer Series. This particular part is primarily about 3-D, but
|
||
also includes a bit on optimisation.
|
||
|
||
If you are already a 3-D guru, you may as well skip this text file, have
|
||
a quick look at the sample program then go back to sleep, because I am
|
||
going to explain in minute detail exactly how the routines work ;)
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write a message in the Programming conference on the
|
||
For Your Eyes Only BBS (of which I am the Moderator )
|
||
This is preferred if you have a general programming query
|
||
or problem others would benefit from.
|
||
4) Write to Denthor, EzE or Goth on Connectix.
|
||
5) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity)
|
||
7) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
|
||
mention the word Denthor near the top of the letter.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Optimisation
|
||
|
||
Before I begin with the note on 3-D, I would like to stress that many of
|
||
these routines, and probably most of your own, could be sped up quite a
|
||
bit with a little optimisation. One must realise, however, that you must
|
||
take a look at WHAT to optimise ... converting a routine that is only
|
||
called once at startup into a tightly coded assembler routine may show
|
||
off your merits as a coder, but does absolutely nothing to speed up your
|
||
program. Something that is called often per frame is something that
|
||
needs to be as fast as possible. For some, a much used procedure is the
|
||
PutPixel procedure. Here is the putpixel procedure I gave you last week:
|
||
|
||
Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
|
||
BEGIN
|
||
Asm
|
||
push ds { 14 clock ticks }
|
||
push es { 14 }
|
||
mov ax,[where] { 8 }
|
||
mov es,ax { 2 }
|
||
mov bx,[X] { 8 }
|
||
mov dx,[Y] { 8 }
|
||
push bx { 15 }
|
||
mov bx, dx { 2 }
|
||
mov dh, dl { 2 }
|
||
xor dl, dl { 3 }
|
||
shl bx, 1 { 2 }
|
||
shl bx, 1 { 2 }
|
||
shl bx, 1 { 2 }
|
||
shl bx, 1 { 2 }
|
||
shl bx, 1 { 2 }
|
||
shl bx, 1 { 2 }
|
||
add dx, bx { 3 }
|
||
pop bx { 12 }
|
||
add bx, dx { 3 }
|
||
mov di, bx { 2 }
|
||
xor al,al { 3 }
|
||
mov ah, [Col] { 8 }
|
||
mov es:[di],ah { 10 }
|
||
pop es { 12 }
|
||
pop ds { 12 }
|
||
End;
|
||
END;
|
||
Total = 153 clock ticks
|
||
NOTE : Don't take my clock ticks as gospel, I probably got one or two
|
||
wrong.
|
||
|
||
Right, now for some optimising. Firstly, if you have 286 instructions
|
||
turned on, you may replace the 6 shl,1 with shl,6. Secondly, the Pascal
|
||
compiler automatically pushes and pops ES, so those two lines may be
|
||
removed. DS:[SI] is not altered in this procedure, so we may remove
|
||
those too. Also, instead of moving COL into ah, we move it into AL and
|
||
call stosb (es:[di]:=al; inc di). Let's have a look at the routine now :
|
||
|
||
Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
|
||
BEGIN
|
||
Asm
|
||
mov ax,[where] { 8 }
|
||
mov es,ax { 2 }
|
||
mov bx,[X] { 8 }
|
||
mov dx,[Y] { 8 }
|
||
push bx { 15 }
|
||
mov bx, dx { 2 }
|
||
mov dh, dl { 2 }
|
||
xor dl, dl { 3 }
|
||
shl bx, 6 { 8 }
|
||
add dx, bx { 3 }
|
||
pop bx { 12 }
|
||
add bx, dx { 3 }
|
||
mov di, bx { 2 }
|
||
mov al, [Col] { 8 }
|
||
stosb { 11 }
|
||
End;
|
||
END;
|
||
Total = 95 clock ticks
|
||
|
||
Now, let us move the value of BX directly into DI, thereby removing a
|
||
costly push and pop. The MOV and the XOR of DX can be replaced by it's
|
||
equivalent, SHL DX,8
|
||
|
||
Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler;
|
||
asm
|
||
mov ax,[where] { 8 }
|
||
mov es,ax { 2 }
|
||
mov bx,[X] { 8 }
|
||
mov dx,[Y] { 8 }
|
||
mov di,bx { 2 }
|
||
mov bx, dx { 2 }
|
||
shl dx, 8 { 8 }
|
||
shl bx, 6 { 8 }
|
||
add dx, bx { 3 }
|
||
add di, dx { 3 }
|
||
mov al, [Col] { 8 }
|
||
stosb { 11 }
|
||
end;
|
||
Total = 71 clock ticks
|
||
|
||
As you can see, we have brought the clock ticks down from 153 ticks to
|
||
71 ticks ... quite an improvement. (The current ASPHYXIA putpixel takes
|
||
48 clock ticks) . As you can see, by going through your routines a few
|
||
times, you can spot and remove unnecessary instructions, thereby greatly
|
||
increasing the speed of your program.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Defining a 3-D object
|
||
|
||
Drawing an object in 3-D is not that easy. Sitting down and plotting a
|
||
list of X,Y and Z points can be a time consuming business. So, let us
|
||
first look at the three axes you are drawing them on :
|
||
|
||
Y Z
|
||
/|\ /
|
||
| /
|
||
X<-----|----->
|
||
|
|
||
\|/
|
||
|
||
X is the horisontal axis, from left to right. Y is the vertical axis,
|
||
from top to bottom. Z is the depth, going straight into the screen.
|
||
|
||
In this trainer, we are using lines, so we define 2 X,Y and Z
|
||
coordinates, one for each end of the line. A line from far away, in the
|
||
upper left of the X and Y axes, to close up in the bottom right of the
|
||
X and Y axes, would look like this :
|
||
|
||
{ x1 y1 z1 x2 y2 z2 }
|
||
( (-10,10,-10),(10,-10,10) )
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Rotating a point with matrixes
|
||
|
||
NOTE : I thought that more then one matix are matrisese (sp), but my
|
||
spellchecker insists it is matrixes, so I let it have it's way
|
||
;-)
|
||
|
||
Having a 3-D object is useless unless you can rotate it some way. For
|
||
demonstration purposes, I will begin by working in two dimensions, X and
|
||
Y.
|
||
|
||
Let us say you have a point, A,B, on a graph.
|
||
Y
|
||
| /O1 (Cos (a)*A-Sin (a)*B , Sin (a)*A+Cos (a)*B)
|
||
|/ (A,B)
|
||
X<-----|------O-->
|
||
|
|
||
|
|
||
|
||
Now, let us say we rotate this point by 45 degrees anti-clockwise. The
|
||
new A,B can be easily be calculated using sin and cos, by an adaption of
|
||
our circle algorithm, ie.
|
||
A2:=Cos (45)*A - Sin (45)*B
|
||
B2:=Sin (45)*A + Cos (45)*B
|
||
I recall that in standard 8 and 9, we went rather heavily into this in
|
||
maths. If you have troubles, fine a 8/9/10 maths book and have a look;
|
||
it will go through the proofs etc.
|
||
|
||
Anyway, we have now rotated an object in two dimensions, AROUND THE Z
|
||
AXIS. In matrix form, the equation looks like this :
|
||
|
||
[ Cos (a) -Sin (a) 0 0 ] [ x ]
|
||
[ Sin (a) Cos (a) 0 0 ] . [ y ]
|
||
[ 0 0 1 0 ] [ z ]
|
||
[ 0 0 0 1 ] [ 1 ]
|
||
|
||
I will not go to deeply into matrixes math at this stage, as there are
|
||
many books on the subject (it is not part of matric maths, however). To
|
||
multiply a matrix, to add the products of the row of the left matrix and
|
||
the column of the right matrix, and repeat this for all the columns of the
|
||
left matrix. I don't explain it as well as my first year maths lecturer,
|
||
but have a look at how I derived A2 and B2 above. Here are the other
|
||
matrixes :
|
||
|
||
Matrix for rotation around the Y axis :
|
||
[ Cos (a) 0 -Sin (a) 0 ] [ x ]
|
||
[ 0 1 0 0 ] . [ y ]
|
||
[ Sin (a) 0 Cos (a) 0 ] [ z ]
|
||
[ 0 0 0 1 ] [ 1 ]
|
||
|
||
Matrix for rotation around the X axis :
|
||
[ 1 0 0 ] [ x ]
|
||
[ 0 Cos (a) -Sin (a) 0 ] . [ y ]
|
||
[ 0 Sin (a) Cos (a) 0 ] [ z ]
|
||
[ 0 0 0 1 ] [ 1 ]
|
||
|
||
By putting all these matrixes together, we can translate out 3D points
|
||
around the origin of 0,0,0. See the sample program for how we put them
|
||
together.
|
||
|
||
In the sample program, we have a constant, never changing base object.
|
||
This is rotated into a second variable, which is then drawn. I am sure
|
||
many of you can thing of cool ways to change the base object, the
|
||
effects of which will appear while the object is rotating. One idea is
|
||
to "pulsate" a certain point of the object according to the beat of the
|
||
music being played in the background. Be creative. If you feel up to it,
|
||
you could make your own version of transformers ;)
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Drawing a 3D point to screen
|
||
|
||
Having a rotated 3D object is useless unless we can draw it to screen.
|
||
But how do we show a 3D point on a 2D screen? The answer needs a bit of
|
||
explaining. Examine the following diagram :
|
||
|
||
| ________-------------
|
||
____|___------ o Object at X,Y,Z o1 Object at X,Y,Z2
|
||
Eye -> O)____|___
|
||
| ------________
|
||
| -------------- Field of vision
|
||
Screen
|
||
|
||
Let us pretend that the centre of the screen is the horizon of our
|
||
little 3D world. If we draw a three dimensional line from object "o" to
|
||
the centre of the eye, and place a pixel on the X and Y coordinates
|
||
where it passes through the screen, we will notice that when we do the
|
||
same with object o1, the pixel is closer to the horizon, even though
|
||
their 3D X and Y coords are identical, but "o1"'s Z is larger then
|
||
"o"'s. This means that the further away a point is, the closer to the
|
||
horizon it is, or the smaller the object will appear. That sounds
|
||
right, doesent it? But, I hear you cry, how do we translate this into a
|
||
formula? The answer is quite simple. Divide your X and your Y by your Z.
|
||
Think about it. The larger the number you divide by, the closer to zero,
|
||
or the horizon, is the result! This means, the bigger the Z, the
|
||
further away is the object! Here it is in equation form :
|
||
|
||
nx := 256*x div (z-Zoff)+Xoff
|
||
ny := 256*y div (z-Zoff)+Yoff
|
||
|
||
NOTE : Zoff is how far away the entire object is, Xoff is the objects X
|
||
value, and Yoff is the objects Y value. In the sample program,
|
||
Xoff start off at 160 and Yoff starts off at 100, so that the
|
||
object is in the middle of the screen.
|
||
|
||
The 256 that you times by is the perspective with which you are viewing.
|
||
Changing this value gives you a "fish eye" effect when viewing the
|
||
object. Anyway, there you have it! Draw a pixel at nx,ny, and viola! you
|
||
are now doing 3D! Easy, wasn't it?
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Possible improvements
|
||
|
||
This program is not the most optimised routine you will ever encounter
|
||
(;-)) ... it uses 12 muls and 2 divs per point. (Asphyxia currently has
|
||
9 muls and 2 divs per point) Real math is used for all the calculations
|
||
in the sample program, which is slow, so fixed point math should be
|
||
implemented (I will cover fixed point math in a future trainer). The
|
||
line routine currently being used is very slow. Chain-4 could be used to
|
||
cut down on screen flipping times.
|
||
|
||
Color values per line should be added, base object morphing could be put
|
||
in, polygons could be used instead of lines, handling of more then one
|
||
object should be implemented, clipping should be added instead of not
|
||
drawing something if any part of it is out of bounds.
|
||
|
||
In other words, you have a lot of work ahead of you ;)
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
There are a lot of books out there on 3D, and quite a few sample
|
||
programs too. Have a look at them, and use the best bits to create your
|
||
own, unique 3D engine, with which you can do anything you want. I am
|
||
very interested in 3D (though EzE and Goth wrote most of ASPHYXIA'S 3D
|
||
routines), and would like to see what you can do with it. Leave me a
|
||
message through one of the means described above.
|
||
|
||
I am delving into the murky world of texture mapping. If anyone out
|
||
there has some routines on the subject and are interested in swapping,
|
||
give me a buzz!
|
||
|
||
What to do in future trainers? Help me out on this one! Are there any
|
||
effects/areas you would like a bit of info on? Leave me a message!
|
||
|
||
I unfortunately did not get any messages regarding BBS's that carry this
|
||
series, so the list that follows is the same one from last time. Give
|
||
me your names, sysops!
|
||
|
||
Aaaaargh!!! Try as I might, I can't think of a new quote. Next time, I
|
||
promise! ;-)
|
||
|
||
Bye for now,
|
||
- Denthor
|
||
|
||
|
||
These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º
|
||
ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º
|
||
ºConnectix BBS º(031) 266-9992 ºALL º * º º º
|
||
ºFor Your Eyes Only BBS º(031) 285-318 ºA/H º * º * º * º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ
|
||
|
||
Open = Open at all times or only A/H
|
||
Msg = Available in message base
|
||
File = Available in file base
|
||
Past = Previous Parts available
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 9 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hi there! ASPHYXIA is BACK with our first MegaDemo, Psycho Neurosis! A
|
||
paltry 1.3MB download is all it takes to see the group from Durbs first
|
||
major production! We are quite proud of it, and think you should see it
|
||
;)
|
||
|
||
Secondly, I released a small little trainer (a trainerette ;-)) on
|
||
RsaPROG and Connexctix BBS mail, also on the ASPHYXIA BBS as COPPERS.ZIP
|
||
It is a small Pascal program demonstrating how to display copper bars in
|
||
text mode. Also includes a check for horizontal retrace (A lot of people
|
||
wanted it, that is why I wrote the program) (ASPHYXIA ... first with the
|
||
trainer goodies ;-) aargh, sorry, had to be done ))
|
||
|
||
Thirdly, sorry about the problems with Tut 8! If you had all the
|
||
checking on, the tutorial would probably die on the first points. The
|
||
reason is this : in the first loop, we have DrawPoints then
|
||
RotatePoints. The variables used in DrawPoints are set in RotatePoints,
|
||
so if you put RotatePoints before DrawPoints, the program should work
|
||
fine. Alternatively, turn off error checking 8-)
|
||
|
||
Fourthly, I have had a surprisingly large number of people saying that
|
||
"I get this, like, strange '286 instructions not enabled' message!
|
||
What's wrong with your code, dude?" To all of you, get into Pascal, hit
|
||
Alt-O (for options), hit enter and a 2 (for Enable 286 instructions). Hard
|
||
hey? Doesn't anyone EVER set up their version of Pascal?
|
||
|
||
Now, on to todays tutorial! 3D solids. That is what the people wanted,
|
||
that is what the people get! This tutorial is mainly on how to draw the
|
||
polygon on screen. For details on how the 3D stuff works, check out tut
|
||
8.
|
||
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to Denthor, EzE or Goth on Connectix.
|
||
3) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity)
|
||
5) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
|
||
mention the word Denthor near the top of the letter.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How to draw a polygon
|
||
|
||
Sounds easy enough, right? WRONG! There are many, many different ways to
|
||
go about this, and today I'll only be showing you one. Please don't take
|
||
what is written here as anything approaching the best method, it is just
|
||
here to get you on your way...
|
||
|
||
The procedure I will be using here is based on something most of us
|
||
learned in standard eight ... I think. I seem to recall doing something
|
||
like this in Mrs. Reids maths class all those years ago ;)
|
||
|
||
Take two points, x1,y1 and x2,y2. Draw them :
|
||
|
||
+ (x1,y1)
|
||
\
|
||
\ <-- Point a somewhere along the line
|
||
\
|
||
+ (x2,y2)
|
||
|
||
Right, so what we have to do is this : if we know the y-coord of a, what
|
||
is it's x-coord? To prove the method we will give the points random
|
||
values.
|
||
|
||
+ (2,10)
|
||
\
|
||
\ <-- a.y = 12
|
||
\
|
||
+ (15,30)
|
||
|
||
Right. Simple enough problem. This is how we do it :
|
||
(a.y-y1) = (12 - 10) {to get a.y as though y1 was zero}
|
||
*(x2-x1) = *(15 - 2) {the total x-length of the line}
|
||
/(y2-y1) = /(30 - 10) {the total y-length of the line}
|
||
+x1 = +2 { to get the equation back to real coords}
|
||
|
||
So our equation is : (a.y-y1)*(x2-x1)/(y2-y1)+x4 or
|
||
(12-10)*(15-2)/(30-10)+2
|
||
which gives you :
|
||
2*13/20+2 = 26/20+2
|
||
= 3.3
|
||
|
||
That means that along the line with y=12, x is equal to 3.3. Since we
|
||
are not concerned with the decimal place, we replace the / with a div,
|
||
which in Pascal gives us an integer result, and is faster too. All well
|
||
and good, I hear you cry, but what does this have to do with life and
|
||
how it relates to polygons in general. The answer is simple. For each of
|
||
the four sides of the polygon we do the above test for each y line. We
|
||
store the smallest and the largest x values into separate variables for
|
||
each line, and draw a horizontal line between them. Ta-Dah! We have a
|
||
cool polygon!
|
||
|
||
For example : Two lines going down :
|
||
|
||
+ +
|
||
/ <-x1 x2->| <--For this y line
|
||
/ |
|
||
+ +
|
||
|
||
Find x1 and x2 for that y, then draw a line between them. Repeat for all
|
||
y values.
|
||
|
||
Of course, it's not as simple as that. We have to make sure we only
|
||
check those y lines that contain the polygon (a simple min y, max y test
|
||
for all the points). We also have to check that the line we are
|
||
calculating actually extends as far as where our current y is (check
|
||
that the point is between both y's). We have to compare each x to see
|
||
weather it is smaller then the minimum x value so far, or bigger then
|
||
the maximum (the original x min is set as a high number, and the x max
|
||
is set as a small number). We must also check that we only draw to the
|
||
place that we can see ( 0-319 on the x ; 0-199 on the y (the size of the
|
||
MCGA screen))
|
||
|
||
To see how this looks in practice, have a look at the sample code
|
||
provided. (Mrs. Reid would probably kill me for the above explanation,
|
||
so when you learn it in school, split it up into thousands of smaller
|
||
equations to get the same answer ;))
|
||
|
||
Okay, that's it! What's that? How do you draw a vertical line? Thats
|
||
simple ...
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Drawing a vertical line
|
||
|
||
Right, this is a lot easier than drawing a normal line (Tut 5 .. I
|
||
think), because you stay on the same y value. So, what you do is you set
|
||
ES to the screen you want to write to, and get DI to the start of the
|
||
y-line (see earlier trainers for a description of how SEGMENT:OFFSET
|
||
works.
|
||
|
||
IN : x1 , x2, y, color, where
|
||
|
||
asm
|
||
mov ax,where
|
||
mov es,ax
|
||
mov di,y
|
||
mov ax,y
|
||
shl di,8 { di:=di*256 }
|
||
shl ax,6 { ax:=ax*64 }
|
||
add di,ax { di := (y*256)+(y*64) := y*320 Faster then a
|
||
straight multiplication }
|
||
|
||
Right, now you add the first x value to get your startoff.
|
||
add di,x1
|
||
Move the color to store into ah and al
|
||
mov al,color
|
||
mov ah,al { ah:=al:=color }
|
||
then get CX equal to how many pixels across you want to go
|
||
mov cx,x2
|
||
sub cx,x1 { cx:=x2-x1 }
|
||
Okay, as we all know, moving a word is a lot faster then moving a byte,
|
||
so we halve CX
|
||
shr cx,1 { cx:=cx/2 }
|
||
but what happens if CX was an odd number. After a shift, the value of
|
||
the last number is placed in the carry flag, so what we do is jump over
|
||
a single byte move if the carry flag is zero, or execute it if it is
|
||
one.
|
||
jnc @Start { If there is no carry, jump to label Start }
|
||
stosb { ES:[DI]:=al ; increment DI }
|
||
@Start : { Label Start }
|
||
rep stosw { ES:[DI]:=ax ; DI:=DI+2; repeat CX times }
|
||
|
||
Right, the finished product looks like this :
|
||
|
||
Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
|
||
{ This draws a horizontal line from x1 to x2 on line y in color col }
|
||
asm
|
||
mov ax,where
|
||
mov es,ax
|
||
mov ax,y
|
||
mov di,ax
|
||
shl ax,8
|
||
shl di,6
|
||
add di,ax
|
||
add di,x1
|
||
|
||
mov al,col
|
||
mov ah,al
|
||
mov cx,x2
|
||
sub cx,x1
|
||
shr cx,1
|
||
jnc @start
|
||
stosb
|
||
@Start :
|
||
rep stosw
|
||
end;
|
||
|
||
Done!
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
This 3D system is still not perfect. It needs to be faster, and now I
|
||
have also dumped the problem of face-sorting on you! Nyahahahaha!
|
||
|
||
[ My sister and I were driving along the other day when she
|
||
asked me, what would I like for my computer.
|
||
I thought long and hard about it, and came up with the
|
||
following hypothesis. When a girl gets a Barbie doll, she
|
||
then wants the extra ballgown for the doll, then the
|
||
hairbrush, and the car, and the house, and the friends
|
||
etc.
|
||
When a guy gets a computer, he wants the extra memory, the
|
||
bigger hard drive, the maths co-pro, the better
|
||
motherboard, the latest software, and the bigger monitor
|
||
etc.
|
||
I told my sister all of this, and finished up with : "So as
|
||
you can see, computers are Barbie dolls for MEN!"
|
||
She called me a chauvinist. And hit me. Hard.
|
||
]
|
||
- Grant Smith
|
||
19:24
|
||
26/2/94
|
||
|
||
See you next time!
|
||
- Denthor
|
||
|
||
These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º
|
||
ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º
|
||
ºConnectix BBS º(031) 266-9992 ºALL º º * º * º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ
|
||
|
||
Open = Open at all times or only A/H
|
||
Msg = Available in message base
|
||
File = Available in file base
|
||
Past = Previous Parts available
|
||
|
||
Does no other BBS's ANYWHERE carry the trainer? Am I writing this for
|
||
three people who get it from one of these BBS's each week? Should I go
|
||
on? (Hehehehe ... I was pleased to note that Tut 8 was THE most
|
||
downloaded file from ASPHYXIA BBS last month ... )
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 10 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Wow! The trainer has finally reached part 10! This will also be the
|
||
first part introduced simultaneously to local BBS's and the INTERNET at
|
||
the same time! Yes folks, I put up a copy of previous tutorials onto
|
||
various ftp sites, and awaited the flames saying that the net.gurus
|
||
already knew this stuff, and why was I wasting disk space! The flames
|
||
did not appear (well, except for one), and I got some messages saying
|
||
keep it up, so from now on I will upload all future trainers to ftp
|
||
sites too (wasp.eng.ufl.edu , cs.uwp.edu etc.). I will also leave a
|
||
notice in the USENET groups comp.lang.pascal and comp.sys.ibm.pc.demos
|
||
when a new part is finished (Until enough people say stop ;-))
|
||
|
||
I can also be reached at my new E-Mail address,
|
||
smith9@batis.bis.und.ac.za
|
||
|
||
Well, this tutorial is on Chain-4. When asked to do a trainer on
|
||
Chain-4, I felt that I would be walking on much travelled ground (I have
|
||
seen numerous trainers on the subject), but the people who asked me said
|
||
that they hadn't seen any, so could I do one anyway? Who am I to say no?
|
||
|
||
The sample program attached isn't that great, but I am sure that all you
|
||
people out there can immediately see the potential that Chain-4 holds.
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to Denthor, EzE or Goth on Connectix.
|
||
3) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
5) Write to smith9@batis.bis.und.ac.za in E-Mail.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is Chain-4?
|
||
|
||
You people out there all have at least 256k vga cards. Most of you have
|
||
512k vga cards, and some have 1MB vga cards. But what you see on your
|
||
screen, as discussed in previous trainers, is 64k of data! What happened
|
||
to the other 192k??? Chain-4 is a method of using all 256k at one time.
|
||
|
||
The way this is done is simple. 1 screen = 64k. 64k * 4 = 256k.
|
||
Therefore, chain-4 allows you to write to four screens, while displaying
|
||
one of them. You can then move around these four screens to see the data
|
||
on them. Think of the Chain-4 screen as a big canvas. The viewport,
|
||
the bit you see out of, is a smaller rectangle which can be anywhere
|
||
over the bigger canvas.
|
||
|
||
+----------------------------+ Chain-4 screen
|
||
| +--+ |
|
||
| | | <- Viewport |
|
||
| +--+ |
|
||
| |
|
||
+----------------------------+
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ The size of the chain-4 screen
|
||
|
||
The Chain-4 screen, can be any size that adds up to 4 screens.
|
||
|
||
For example, it can be 4 screens across and one screen down, or one
|
||
screen across and 4 screens down, or two screens across and two screens
|
||
down, and any size in between.
|
||
|
||
In the sample program, the size is a constant. The size * 8 is how many
|
||
pixels across there are on the chain-4 screen, ie
|
||
Size = 40 = 320 pixels across = 1 screen across, 4 screens down
|
||
Size = 80 = 640 pixels across = 2 screens across, 2 screens down
|
||
etc.
|
||
|
||
We need to know the size of the screen for almost all dealings with the
|
||
Chain-4 screen, for obvious reasons.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Layout of the chain-4 screen, and accessing it
|
||
|
||
If you will remember all the way back to Part 1 of this series, I
|
||
explained that the memory layout of the MCGA screen is linear. Ie, the
|
||
top left hand pixel was pixel zero, the one to the right of it was
|
||
number one, the next one was number two etc. With Chain-4, things are
|
||
very different.
|
||
|
||
Chain-4 gets the 4 screens and chains them together (hence the name :)).
|
||
Each screen has a different plane value, and must be accessed
|
||
differently. The reason for this is that a segment of memory is only 64k
|
||
big, so that we could not fit the entire Chain-4 screen into one
|
||
segment.
|
||
|
||
All Chain-4 screens are accessed from $a000, just like in MCGA mode.
|
||
What we do is, before we write to the screen, find out what plane we are
|
||
writing to, set that plane, then plot the pixel. Here is how we find out
|
||
how far in to plot the pixel and what plane it is on :
|
||
|
||
Instead of the linear model of MCGA mode, ie :
|
||
ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
|
||
³00³01³02³03³04³05³06³07³08³09³10³11³ ...
|
||
|
||
Each plane of the Chain-4 screen accesses the memory in this way :
|
||
|
||
Plane 0 :
|
||
ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
|
||
³00³ ³ ³ ³01³ ³ ³ ³02³ ³ ³ ³ ...
|
||
|
||
Plane 1 :
|
||
ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
|
||
³ ³00³ ³ ³ ³01³ ³ ³ ³02³ ³ ³ ...
|
||
|
||
Plane 2 :
|
||
ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
|
||
³ ³ ³00³ ³ ³ ³01³ ³ ³ ³02³ ³ ...
|
||
|
||
Plane 3 :
|
||
ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
|
||
³ ³ ³ ³00³ ³ ³ ³01³ ³ ³ ³02³ ...
|
||
|
||
In this way, by choosing the right plane to write to, we can access all
|
||
of the 256k of memory available to us. The plane that we write to can
|
||
easily be found by the simple calculation of x mod 4, and the x
|
||
coordinate is also found by x div 4. We work out our y by multiplying
|
||
it by the size of our chain-4 screen.
|
||
|
||
NOTE : It is possible to write to all four planes at once by setting the
|
||
correct port values.
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Uses of Chain-4
|
||
|
||
The uses of Chain-4 are many. One could write data to one screen, then
|
||
flip to it (the move_to command is almost instantaneous). This means
|
||
that 64k of memory does not need to be set aside for a virtual screen,
|
||
you are using the vga cards memory instead!
|
||
|
||
Scrolling is much easier to code for in Chain-4 mode.
|
||
|
||
It is possible to "tweak" the mode into other resolutions. In our demo,
|
||
our vectors were in 320x240 mode, and our dot vectors were in 320x400
|
||
mode.
|
||
|
||
The main disadvantage of chain-4 as I see it is the plane swapping,
|
||
which can be slow. With a bit of clever coding however, these can be
|
||
kept down to a minimum.
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ The sample programs
|
||
|
||
The first sample program is GFX.PAS. This is a until in which I have
|
||
placed most of our routines from previous tuts. All the procedures and
|
||
variables you can see under the INTERFACE section can be used in any
|
||
program with GFX in the USES clause. In other words, I could do this :
|
||
|
||
USES GFX,crt;
|
||
|
||
BEGIN
|
||
Setupvirtual;
|
||
cls (vaddr,0);
|
||
Shutdown;
|
||
END.
|
||
|
||
This program would compile perfectly. What I suggest you do is this :
|
||
Rename the file to a name that suites you (eg your group name), change
|
||
the first line of the unit to that name, then add all useful procedures
|
||
etc. to the unit. Make it grow :-).
|
||
|
||
The second file is the sample program (note the USES GFX,crt; up near
|
||
the top!). The program is easy to understand and is documented. The bit
|
||
that I want to draw your attention to is the constant, BIT. Because I
|
||
am distributing this file to many places in text form, not binary form,
|
||
I could not just add a .CEL file with the program. So what I did was
|
||
write some text in one color then saved it as a .CEL . I then wrote a
|
||
ten line program that did the following : Moving from left to right, it
|
||
counted how many pixels were of color zero, then saved the byte value to
|
||
an array. When it came across color one, is counted for how long that
|
||
went on then saved the byte value and saved it to an array and so on.
|
||
When it was finished, I converted the array into a text file in the
|
||
CONST format. Not too cunning, but I thought I had better explain it ;-)
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
There are other documents and sample programs available on Chain-4 and
|
||
it's like : Try XLIB for one...
|
||
|
||
Finally! Some BBS's have joined my BBS list! (Okay, only two new ones,
|
||
but it's a start ;-)) All you international BBS's! If you will regularly
|
||
download the tuts from an FTP site, give me your names!
|
||
|
||
I own a car. The car's name is Bob. A few days ago, Bob was in an
|
||
accident, and now has major damage to his front. Knowing insurance, I
|
||
probably won't get much, probably nothing (the other guy wasn't insured,
|
||
and I am only 18 :( ). I will probably have to find work in order to pay
|
||
for my repairs. The point to this meandering is this : I am upset, so if
|
||
you think you are getting a quote, you can just forget it.
|
||
|
||
Oh, well. Life goes on!
|
||
|
||
See you next time,
|
||
- Denthor
|
||
|
||
These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º
|
||
ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º
|
||
ºConnectix BBS º(031) 266-9992 ºALL º º * º * º
|
||
ºPOP! º(012) 661-1257 ºALL º º * º * º
|
||
ºPure Surf BBS º(031) 561-5943 ºA/H º º * º * º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ
|
||
|
||
For international users : If you live outside the Republic of South
|
||
Africa, do the following : Dial +27, dont dial the first 0, but dial
|
||
the rest of the number. Eg, for the ASPHYXIA BBS : +27-31-765-5312
|
||
|
||
Open = Open at all times or only A/H
|
||
Msg = Available in message base
|
||
File = Available in file base
|
||
Past = Previous Parts available
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 11 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hello again everybody!
|
||
|
||
The reason _this_ one is delayed (every single trainer has been so far ;))
|
||
is mainly due to a birthday (my 19th), and numerous tests at the
|
||
university (ugh!). But anyway, here it is. The sample program this time
|
||
is on cross-fading. The reason for this is that many people have
|
||
commented that I should be moving over to a few basic demo effects now
|
||
that we have most of the basics of VGA programming. I was also thinking
|
||
of either doing sound in a future version of this trainer, or starting a
|
||
separate "ASPHYXIA Sound Tutorial" series. Comments?
|
||
|
||
One major difference between this trainer and previous ones is that I am
|
||
including binary files (pictures in this case). This means that it will
|
||
not be available in the message bases of selected boards anymore, and it
|
||
must be obtained from the file base. Notice will however be given of
|
||
it's existence in the message base.
|
||
|
||
Asphyxia has formalised things a bit, and we now have a few official
|
||
distribution sites for all our demos and trainers. If you would like
|
||
your BBS to become a distribution site, please email me at
|
||
smith9@batis.bis.und.ac.za and I will send you the necessary info.
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to Denthor, EzE, Goth, Fubar or Nobody on Connectix.
|
||
3) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
5) Write to smith9@batis.bis.und.ac.za in E-Mail.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is a "Crossfade"?
|
||
|
||
This is a simple question. When you are watching a TV program, you will
|
||
often see one picture on the screen, which slowly fades to a new
|
||
picture, with the new picture becoming more and more prominent and the
|
||
old one becoming less and less prominent. This is a crossfade. Easy huh?
|
||
|
||
Perhaps, but it is not that easy to code on a computer...
|
||
|
||
In most demos, there is a crossfade of two colors, black and white, for
|
||
example : The words 'MYDEMOTEAM' appears in large with letters, then
|
||
crossfades to 'PRESENTS' in large white letters.
|
||
|
||
I decided to allow the programmer to have a bit of color to his
|
||
crossfade, and the sample program can handle a many color crossfade.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How does a crossfade work?
|
||
|
||
Here comes the clever bit.
|
||
|
||
To do a crossfade, we load in two pictures, FROM and TO. Then, for every
|
||
pixel in which they are different, put a new pixel in a third screen.
|
||
|
||
For example, wherever there is pixel color 9 on screen 1 and pixel color
|
||
45 on screen 2, put pixel color 1 on the third screen. You then repeat
|
||
this for all combinations of pixels on screen one and two, and put the
|
||
results into screen 3. Here it is in ascii ...
|
||
|
||
Screen 1 Screen 2 Screen 3
|
||
.1... .3... .1...
|
||
..... ..2.. ..2..
|
||
...8. + ...1. = ...3.
|
||
.1... ....2 .4..2
|
||
|
||
Note how the values on screen 3 are sequential? We keep a count for
|
||
this... The two "2"'s on screen 3 are identical, so we do not use a new
|
||
color for it...
|
||
|
||
We also keep to pallettes ... source and dest.
|
||
|
||
For the above example source[1] would be the pallette of 1 in screen 1,
|
||
and dest[1] would be the pallette of 3 in screen 2 (Note that screen 1
|
||
and screen 2 have different pallettes)
|
||
|
||
When we are finished with the picture, we flip screen 3 to the vga and
|
||
do the following : move the pallette from source to dest or vice versa.
|
||
Thats it. No fancy screen manipulations for the crossfade, we just
|
||
change the pallette. Cool, huh? It also means that you can be doing fun
|
||
stuff in the foreground with unused pallette colors without your program
|
||
executing at two frames per second ;)
|
||
|
||
The sample program is fully documented, and you shouldn't have a problem
|
||
deciphering it... If you ever use this effect in a demo or game, greet
|
||
me! :-)
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Problems with crossfades
|
||
|
||
The main problem with crossfading is this : there may only be 256 colors
|
||
on screen 3, in other words, only 256 combinations of colors. In the
|
||
sample program, if you load up two pics with more then 256 combinations,
|
||
the program gives an error message and exits to dos. To sort this
|
||
problem out, you can do two things : reduce the number of places where
|
||
the two pictures intersect, or squeeze down the pallette, using
|
||
Autodesk Animators "SQUEEZE" command. This reduces the number of colors
|
||
used by the picture, and therefore reduces the number of combinations.
|
||
The picture does however lose a bit of quality.
|
||
|
||
The second problem with crossfading is this : It hogs most of the
|
||
colors. Whatever you want to do in the foreground, make sure you do it
|
||
with as few colors as possible.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
So, what do you think? Should I continue with demo effects, or should I
|
||
find more basic things to do? Perhaps I should stop and just do sound
|
||
coding from now on? It is up to you, so leave me mail.
|
||
|
||
You will notice that the sample program can load in any .CEL files, you
|
||
needn't be restricted by the ones I have given you. Try crossfading a
|
||
few of your own pictures and see how it turns out. The picture of the
|
||
robot was draw by Fubar for our demo Psycho Neurosis, and I then
|
||
squeezed down the pallette somewhat in order for the crossfade to work.
|
||
The word "ASPHYXIA" was drawn by me, also in Autodesk Animator.
|
||
|
||
Oh well, I had better get this off quickly, today is the last time for
|
||
the next few days that I can get on to the Net. I will also be voting
|
||
tomorrow! If I see a CNN camera, I'll wave (Thats me, the one on the
|
||
left in the red shirt! ;-)) The next trainer will be coming from the
|
||
New South Africa (TM)
|
||
|
||
See you next time!
|
||
- Denthor
|
||
- 9:16, 26 April, 1994
|
||
|
||
PS. Does anyone in Holland with net access want to act as a courier
|
||
between myself and the Accidental Connection BBS? Please leave me mail
|
||
at smith9@batis.bis.und.ac.za ....
|
||
|
||
The following are official ASPHYXIA distribution sites :
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen º
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º
|
||
ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º
|
||
ºConnectix BBS º+27-31-266-9992 ºALL º
|
||
ºPOP! º+27-12-661-1257 ºALL º
|
||
ºPure Surf BBS º+27-31-561-5943 ºA/H º
|
||
ºWasted Image º407-838-4525 ºALL º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ
|
||
|
||
Leave me mail if you want to become an official Asphyxia BBS
|
||
distribution site.
|
||
|
||
(I will find out the country code for Wasted Image later...)
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 12 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hello! :-)
|
||
|
||
Well, a lot has happened since the last trainer, which is the reason for
|
||
the amazingly long delay. First, the elections. These were quite easy
|
||
actually, I went and watched a move (Demolition Man) (Election day
|
||
special, all movies R2, which is about 50 US cents), then went and voted
|
||
after most voters had gone home, so no long lines ;-). Soon after were
|
||
exams. These did not go too well, and I am not looking forward to the
|
||
results. Finally, I got measles and pneumonia at the same time and was
|
||
sent off to hospital for a few days. All in all, not events which are
|
||
conducive to coding! This has meant that the trainer has been delayed,
|
||
and ASPHYXIA was not able to enter into the local democompo, Dexterity
|
||
'94, which we were hoping to do well in. Oh well, onward and upward!
|
||
|
||
This trainer is on full screen scrolling in Chain-4, by request. This is
|
||
actually very easy to do (and smooth), and holds a lot of potential, as
|
||
I am sure you can immediately imagine.
|
||
|
||
A few more things : People have been saying they have had hassles
|
||
sending me email, and I have found that this is because they forget the
|
||
numbers in my name. They send mail to smith@batis... which does not
|
||
exist, or smith@beastie... which is my brothers account. He is getting a
|
||
bit sick of forwarding my mail to me ;). The two address are :
|
||
smith9@batis.bis.und.ac.za
|
||
smith0@beastie.cs.und.ac.za
|
||
|
||
I have lost about 200k worth of email, chalk it up to my beginner status
|
||
at Unix. The test to see if your mail got through? I have answered
|
||
_every_ email message sent to me (no easy task), so if you haven't got a
|
||
reply, please resend the message.
|
||
|
||
You can now also send a group message to all members of Asphyxia. Just
|
||
send mail to asphyxia@beastie.cs.und.ac.za and we will all get a copy
|
||
... which could mean numerous replies to one querey ;)
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to Denthor, EzE, Goth, Fubar or Nobody on Connectix.
|
||
3) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
5) Write to smith9@batis.bis.und.ac.za in E-Mail.
|
||
6) Write to asphyxia@beastie.cs.und.ac.za
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is full screen scrolling?
|
||
|
||
I seem to recall doing this in a previous tut, but here goes again! Full
|
||
screen scrolling is when the entire screen moves in a particular
|
||
direction, with the new picture scrolling on to the screen. Um. Think of
|
||
movie credits. The screen, filled with text, is scrolled off the top of
|
||
the screen while the new text is scrolled on from the bottom. This is
|
||
full screen scrolling.
|
||
|
||
Full screen scrolling is not limited to movie credits. Games like Raptor
|
||
have you flying over a scrolling landscape while you are shooting down
|
||
the bad guys. In this tutorial we will be doing vertical scrolling, but
|
||
the code can very easily be altered for horizontal scrolling too.
|
||
|
||
Remember that we will be using Chain-4 to do our scrolling, so you may
|
||
want to brush up on tut 10 in which that was covered. I will assume a
|
||
brief knowledge of how chain-4 works for this tutorial.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ The theory
|
||
|
||
The theory behind full screen scrolling in Chain-4 is acually very
|
||
simple.
|
||
|
||
Picture if you will, a screen that is two monitors high. Chain-4
|
||
actually has four, but for this we only need two. Now, for this screen
|
||
that is two monitors high, we can only see one monitors worth. Here it
|
||
is in ASCII
|
||
|
||
+-------------+ Screen two monitors high
|
||
| |
|
||
| |
|
||
| |
|
||
| |
|
||
|+-----------+|
|
||
|| ||
|
||
|| ||<- This is the bit we can see, one monitors worth
|
||
|| ||
|
||
|+-----------+|
|
||
+-------------+
|
||
|
||
We can move the bit we can see up or down the enlarged screen. So, for
|
||
example, if the screen two monitors high had a picture on it, we could
|
||
move the bit we see up and down to try glimpse the entire picture. Think
|
||
of it in this way : The screen is a large painting, but we can only see
|
||
though a small magnifing glass. We can move this magnifing glass around
|
||
the painting, but can never see the painting all at once.
|
||
|
||
This actually works in our favour. Anything done outside the bit we are
|
||
looking through cannot be seen, so we can do our work without changing
|
||
our screen.
|
||
|
||
On to scrolling. The method we will use this time is as follows :
|
||
|
||
1) Draw the next line to be seen just above and just below the part we
|
||
can see.
|
||
|
||
+------------+ The enlarged screen
|
||
| |
|
||
| |
|
||
|111111111111| The new part of the picture
|
||
|+----------+|
|
||
|| || The bit we can see
|
||
|+----------+|
|
||
|111111111111| The new part of the picture
|
||
+------------+
|
||
|
||
2) Move the view up one pixel so that the new part of the picture is
|
||
visible at the top of the screen.
|
||
|
||
3) Repeat Steps 1) and 2) until the whole screen is filled. Our screen
|
||
will look as follows :
|
||
|
||
+---------------+
|
||
|+-------------+|
|
||
||3333333333333||
|
||
||2222222222222|| Viewscreen
|
||
||1111111111111||
|
||
|+-------------+|
|
||
|333333333333333|
|
||
|222222222222222|
|
||
|111111111111111|
|
||
+---------------+
|
||
|
||
Check this picture with steps 1) and 2), you will see that this is
|
||
correct.
|
||
|
||
4) Set our viewport to the bottom of the enlarged screen.
|
||
|
||
+---------------+
|
||
|333333333333333|
|
||
|222222222222222|
|
||
|111111111111111|
|
||
|+-------------+|
|
||
||3333333333333||
|
||
||2222222222222|| New position of viewscreen
|
||
||1111111111111||
|
||
|+-------------+|
|
||
+---------------+
|
||
|
||
As you can see, the bit we will be looking at is exactly the same as
|
||
before, we are now just at the bottom of the larger screen instead of
|
||
the top!
|
||
|
||
5) Jump back to 1). The entire sequence can begin again, and we can have
|
||
infinate scrolling in the upward direction. Clever huh?
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Our code
|
||
|
||
In the sample code, we have 21 different icons. What we do is decide
|
||
what the next row of icons is going to consist of. We then draw the next
|
||
line of pixels above and below the viewscreen according to what icons we
|
||
are displaying. We then scroll up one pixel and begin again. When we
|
||
have completed a row of icons, we randomly select a new row and begin
|
||
again. Our icons are 16x16, so exactly 20 fit across a 320 pixel screen.
|
||
|
||
When we hit the top of our enlarged screen, we flip down to the bottom
|
||
which looks exactly the same as the screen we have left. In this manner
|
||
we have obtained smooth, infinate full screen scrolling!
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Extra bits
|
||
|
||
As you will see from the code, it would be the work of but a few minutes
|
||
to extend our landscape across the two unused screens, thereby allowing
|
||
limited horizontal movement along with our vertical movement. In fact,
|
||
the entire routine could easily be made to be a horizontal scrolling
|
||
routine.
|
||
|
||
A map of sorts could be generated, with one byte equalling one terrain
|
||
type. In this manner, the terrain scrolled over could be set, as in a
|
||
flying game (Flying Shark, Raptor etc). The terrain could also easily be
|
||
replaced with letters for our movie-style credits.
|
||
|
||
Free direction scrolling, ie scrolling in all directions, is a very
|
||
different matter, with very different methods to get it to work. Perhaps
|
||
this will be discussed in a later trainer. But for now, work with this,
|
||
know it, understand it, and think up many great things to do with it!
|
||
How about a full screen text scrolly? A game? Go wild!
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
Well, I hope you enjoyed this, the latest trainer. The sample program is
|
||
a little short, but that is because the concept is so simple. Attached
|
||
is a file, PICCS.DAT, which contains the terrain and letters for the
|
||
sample program. They were .CEL's, which I loaded into the des^ variable,
|
||
which I then dumped to disk, for easy access later. The .CEL's were
|
||
drawn on short notice, but still produces some nice terrain.
|
||
|
||
I have recieved a few requests for future trainers, and most of them are
|
||
for effects, so I guess that is what will be done from now on. A
|
||
surprising number have told me not to do a sound trainer and stick with
|
||
graphics stuff, with only a few asking for sound stuff, so I will hold
|
||
off on that until there is more of a demand.
|
||
|
||
I am still open to suggestions for future trainers, and of course
|
||
suggestions for improving the series. Leave me mail!
|
||
|
||
Hmm. A quote? Okay, let me think ....
|
||
|
||
[ The little devil sat atop the alpine slopes, frolicking in the
|
||
snow. He threw a snowball at a nearby squirrel, which
|
||
missed. The resulting avalance buried two villages and a ski
|
||
resort.
|
||
The little devil was scared. Avalances were bad for
|
||
business. The locals would form team spirit, be nice to
|
||
each other and work together and free those trapped beneath
|
||
the snow, which created even more goodwill. The man
|
||
downstairs didn't like goodwill. He didn't like it at
|
||
all.
|
||
In the blink of an eye the devil was in his penthouse
|
||
apartment, dressed in his usual suit. He picked up the phone.
|
||
Dialing was for mortals.
|
||
"Hello, Micros..."
|
||
"This is Mister Crowley", interrupted the devil.
|
||
There were sounds of thumping on the other side of the
|
||
phone, then there was a new voice. "Hello, Bill here, we
|
||
haven't heard from you in a while, Mister Crowley." The fear
|
||
of the man on the other end was almost tangible. The devil
|
||
smiled.
|
||
"Hello Bill. Something has come up."
|
||
"No!" The man on the other side almost shouted with terror.
|
||
"Not Win..."
|
||
"Yes, Bill. It is time."
|
||
"Havn't I paid enough for my sins? Just that one night..."
|
||
The man was almost sobbing.
|
||
"You are touching me, Bill. But nevertheless, it is time."
|
||
"No." The man sounded beaten, alone.
|
||
"Yes. Bill, it is time for a new update."
|
||
]
|
||
- Grant Smith
|
||
14:23
|
||
23-7-94
|
||
|
||
See you next time!
|
||
- Denthor
|
||
|
||
The following are official ASPHYXIA distribution sites :
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen º
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º
|
||
ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º
|
||
ºC-Spam BBS º410-531-5886 ºALL º
|
||
ºConnectix BBS º+27-31-266-9992 ºALL º
|
||
ºPOP! º+27-12-661-1257 ºALL º
|
||
ºPure Surf BBS º+27-31-561-5943 ºA/H º
|
||
ºSoul Asylum º+358-0-5055041 ºALL º
|
||
ºWasted Image º407-838-4525 ºALL º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ
|
||
|
||
Leave me mail if you want to become an official Asphyxia BBS
|
||
distribution site.
|
||
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 13 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hello again! Here I am, cooped up at home, recovering from my illness
|
||
with nothing to do, so of course it is the perfect time to write another
|
||
trainer! After the long delay between parts 11 and 12, two trainers in
|
||
two days doesn't sound like a bad idea.
|
||
|
||
This trainer is on starfields, which is by request of more then one
|
||
person. This is quite an easy effect, and you should have no trouble
|
||
grasping the concept behind it. I will be doing a 3d starfield, a
|
||
horizontal starfield is very easy with you merely incrementing a x-value
|
||
for each star for each frame. I am not even going to bother doing code
|
||
for that one (unless requested).
|
||
|
||
So I am off to go grab my antibiotics pills and I will be right back
|
||
with the tutorial! ;-)
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to Denthor, EzE, Goth, Fubar or Nobody on Connectix.
|
||
3) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
5) Write to smith9@batis.bis.und.ac.za in E-Mail.
|
||
6) Write to asphyxia@beastie.cs.und.ac.za
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is a 3d starfield?
|
||
|
||
I am not even sure if I should do this bit. Go watch any episode of Star
|
||
Trek, the movies, Star Wars, or just about any sci-fi movie. Somewhere
|
||
there will be a scene where you can see stars whizzing past the
|
||
viewscreen, with the ones that are further away moving slower then the
|
||
ones that are passed quite close to.
|
||
|
||
This is a 3d starfield. If you look closely, you will see that all the
|
||
stars seem to originate from a point, the point you are travelling
|
||
towards. This is an illusion which thankfully happens automatically,
|
||
you don't have to code for it ;)
|
||
|
||
Starfields look very nice, and can make a big difference to an otherwise
|
||
black background. It also makes a great screen saver ;-)
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do they work?
|
||
|
||
This is actually quite simple. Imagine if you will, each star in the
|
||
heavens having an x,y and z coordinate, with you being at 0,0,0. Easy?
|
||
Right. Now, if you were to say move forward, ie. increase your z value,
|
||
to you you will still be at 0,0,0 , but all the stars z values would
|
||
have appeared to decrease by the exact same amount.
|
||
|
||
In easier language, we decrease the z value of all the the stars so that
|
||
they come closer to you, and eventually whizz past.
|
||
|
||
This solves all our problems. Stars that are close to us on the x and y
|
||
scales will pass us by faster then those that are very far from us on
|
||
the x and y scales. The only thing we must watch out for is that no star
|
||
is at 0,0 , ie. exactly in front of us, otherwise there will be a
|
||
collision which will not look good.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do we code this?
|
||
|
||
The first thing to be done is to generate our starfield. This is quite
|
||
easy, with us choosing x values between -160 and 160, and y values
|
||
between -100 and 100 randomly. Each z is sequentially greater for each
|
||
star so that we don't get large areas with no stars. We must remember to
|
||
check that there are no stars at 0,0!
|
||
|
||
Okay, now we start the actual viewing section. Here are the steps :
|
||
|
||
1) Convert our 3-d coords into their 2-d versions. Have a look at tut 8
|
||
to see how this is done, but basically we divide by z.
|
||
|
||
2) Clear away all old stars that may be on the screen.
|
||
|
||
3) Draw all our stars according to our 2-d values we have calculated in
|
||
1)
|
||
|
||
4) Move all the stars either closer to us or further away from us by
|
||
decreasing or increasing their z values respectively.
|
||
|
||
5) If a star's z value has passed into the negative, place it at the
|
||
very back of our "queue" so that it will come around again
|
||
|
||
6) Jump back to 1) ad-infinitum.
|
||
|
||
That is, as they say, it. In our sample program the steps have been
|
||
neatly placed into individual procedures for easy reading.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What next?
|
||
|
||
Okay, so now we have a cool looking starfield. What next? How about
|
||
adding left and right motion? A menu or a scrolly in the foreground? How
|
||
about figuring out how a star tunnel works? A cool 3d routine going in
|
||
front of the stars?
|
||
|
||
A starfield can make just about any routine look just that much more
|
||
professional, and can itself be improved to be a great effect all on
|
||
it's own.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
So, this was yet another effect in the series. Do you still want more
|
||
effects, or what? Leave me mail with further ideas for trainers. I may
|
||
not do it if you don't ask for it!
|
||
|
||
Oh, well, the medicine has been taken, it is time for me to go. Hello to
|
||
all those people who have sent me mail, and those great guys on #coders
|
||
in IRC (you know who you are). Wow. That is the first greets I have ever
|
||
done in a trainer. Hmm. Maybe I'm just ill ;-)
|
||
|
||
Happy coding people!
|
||
- Denthor
|
||
19:28
|
||
24-7-94
|
||
|
||
The following are official ASPHYXIA distribution sites :
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen º
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º
|
||
ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º
|
||
ºC-Spam BBS º410-531-5886 ºALL º
|
||
ºConnectix BBS º+27-31-266-9992 ºALL º
|
||
ºPOP! º+27-12-661-1257 ºALL º
|
||
ºSoul Asylum º+358-0-5055041 ºALL º
|
||
ºWasted Image º407-838-4525 ºALL º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ
|
||
|
||
Leave me mail if you want to become an official Asphyxia BBS
|
||
distribution site.
|
||
|
||
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 14 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hello there. Exams are just around the corner (again :( ), so I thought
|
||
I better get round to doing the next trainer. As usual, there seems to
|
||
have been a big delay between this one and the last one... sorry about
|
||
that ;-)
|
||
|
||
Well, this trainer is mainly on four things : Glenzing, faster polys,
|
||
fixed point and assembler. The sample program is basically tut 9
|
||
rewritten to include the above.
|
||
|
||
I'll go through them in order, and hopefully you won't have any hassles
|
||
grasping the concepts. By the way, do any of you read the text files? I
|
||
find myself answering questions via E-Mail etc. that were discussed in
|
||
the text sections of the trainers ... oh well, I'll just ramble along
|
||
anyway ;-)
|
||
|
||
Please dont send any mail to smith9@batis.bis.und.ac.za anymore ... I
|
||
don't know for how much longer the account will be valid (How can a
|
||
non-BIS person get onto the BIS UNIX machine in the BIS2 directory? If
|
||
his name is Denthor I suppose ;-) Oh well, I got about 8 months use out
|
||
of it. The account expires on Christmas day anyway...) So anyway, please
|
||
leave all messages to denthor@beastie.cs.und.ac.za
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
|
||
5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
|
||
us at once.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is glenzing?
|
||
|
||
This is an easy one. Imagine, in a 3D object, that all the sides are
|
||
made out of colored glass. That means that every time you look through
|
||
that side, everything behind it is tinged in a certain color.
|
||
|
||
In ascii ...
|
||
+---------+
|
||
| <--|---Light blue
|
||
| |
|
||
+--------+ |
|
||
| | <-|-----|---Dark blue
|
||
| +---|-----+
|
||
| <--|---------Light blue
|
||
+--------+
|
||
|
||
So where the two sides overlap, the color values of the two sides are
|
||
added. Easy huh? It is also easy to code. This is how you do it :
|
||
|
||
Set up your pallette to be a nice run of colors.
|
||
Draw your first poly.
|
||
While drawing poly 1, instead of plonking down a set pixel color, grab the
|
||
backgrond pixel, add 1 to it, then put the result down.
|
||
Draw your second poly.
|
||
While drawing poly 2, instead of plonking down a set pixel color, grab the
|
||
backgrond pixel, add 2 to it, then put the result down.
|
||
and so forth.
|
||
|
||
So if the color behind poly 1 was 5, you would place pixel 6 down
|
||
instead.
|
||
|
||
If you do this for every single pixel of every single side of your 3d
|
||
object, you then have glenzing going. This is obviously slightly slower
|
||
then just drawing an item straight, but in the sample program it goes
|
||
quite quickly ... this is because of the following sections...
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Faster Polygons
|
||
|
||
In Tut 9, you probably noticed that we were using a multiply for every
|
||
single line of the poly that we drew. This is not good. Let's find out
|
||
how to speed it up, shall we...
|
||
|
||
With the multiply method, we went through every line, to find out the
|
||
minimum x and maximum x value for that line.
|
||
|
||
+
|
||
------/---\------- Find min x and max x, draw a line
|
||
/ \ between them.
|
||
+ +
|
||
\ /
|
||
\ /
|
||
+
|
||
|
||
How about if we found out all the min and max x's for every line first,
|
||
then just went through an array drawing them. We could do it by
|
||
"scanning" each side in turn. Here is how we do it :
|
||
|
||
+ 1
|
||
/
|
||
/
|
||
2 +
|
||
|
||
We go from point one to point two. For every single y we go down, we
|
||
move a constant x value. This value is found like this :
|
||
|
||
xchange := (x1-x2)/(y1-y2)
|
||
|
||
Remember gradients? This is how you calulated the slope of a line waaay
|
||
back in school. You never thought it would be any use, didn't you ;-)
|
||
|
||
Anyway, with this value, we can do the following :
|
||
|
||
For loop1:=y1 to y2 do BEGIN
|
||
[ Put clever stuff here ]
|
||
x:=x+xchange;
|
||
END;
|
||
|
||
and we will go through all the x-values we need for that line. Clever,
|
||
huh?
|
||
|
||
Now for the clever bit. You have an array, from 0 to 199 (which is all
|
||
the possible y-values your onscreen poly can have). Inside this is two
|
||
values, which will be your min x and your max x. You start off with the
|
||
min x being a huge number, and the max x being a low number. Then you
|
||
scan a side. For each y, check to see if one of the following has
|
||
happened : If the x value is smaller then the xmin value in your
|
||
array, make the xmin value equal to the x value
|
||
If the x value is larger then the xmax value in your
|
||
array, make the xmax value equal to the x value
|
||
|
||
The loop now looks like this :
|
||
|
||
For loop1:=y1 to y2 do BEGIN
|
||
if x>poly[loop1,1] then poly[loop1,1]:=x;
|
||
if x<poly[loop1,1] then poly[loop1,1]:=x;
|
||
x:=x+xchange;
|
||
END;
|
||
|
||
Easy? Do this for all four sides (you can change this for polys with
|
||
different numbers of sides), and then you have all the x min and x max
|
||
values you need to draw your polygon.
|
||
|
||
In the sample program, if you replaced the Hline procedure with one that
|
||
draws solid lines, you could use the given drawpoly for solids.
|
||
|
||
Even this procedure is sped up by the next section, on fixed point.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is fixed point?
|
||
|
||
Have you ever noticed how slow reals are? I mean slooooow. You can get a
|
||
massive speed increase in most programs by replacing your reals with
|
||
integers, words etc. But, I hear you cry, what happens to the much
|
||
needed fraction bit after the decimal point? The answer? You keep it.
|
||
Here's how.
|
||
|
||
Let us say you have a word, which is 16 bits. If you want to use it as a
|
||
fixed point value, you can separate it into 2 sections, one of which
|
||
holds the whole value, and one which holds the fraction.
|
||
|
||
00000000 00000000 <-Bits
|
||
Whole Fraction
|
||
|
||
The number 6.5 would therefore be shown as follows :
|
||
|
||
Top byte : 6
|
||
Bottom byte : 128
|
||
|
||
128 is half (or .5) of 256, and in the case of the fraction section, 256
|
||
would equal one whole number.
|
||
|
||
So let us say we had 6.5 * 2. Using reals this would be a slow mul, but
|
||
with fixed point ...
|
||
|
||
Top Byte : 6
|
||
Bottom Byte : 128
|
||
Value : 1664 <-This is the true value of the word
|
||
ie. (top byte*256)+bottom byte).
|
||
this is how the computer sees the
|
||
word.
|
||
1664 shl 1 = 3328 <-shl 1 is the same as *2, just faster.
|
||
Top byte : 13
|
||
Bottom byte : 0
|
||
|
||
As you can see, we got the correct result! And in a fraction of the time
|
||
that a multiplication of a real would have taken us. You can add and
|
||
subtract fixed point values with no hassles, and multiply and divide
|
||
them by normal values too. When you need the whole value section, you
|
||
can just read the high byte, or do the following
|
||
|
||
whole = word shr 8
|
||
eg 1664 shr 8 = 6
|
||
|
||
As you can see, the fraction is truncated. Obviously, the more bits you
|
||
set aside for the fraction section, the more accurate your calculation
|
||
is, but the lesser the maximum whole number you can have. For example,
|
||
in the above numbers, the maximum value of your whole number was 256, a
|
||
far cry from the 65535 a normal (non fixed point) word's maximum.
|
||
|
||
There are a lot of hassles using fixed point (go on, try shift a
|
||
negative value), most of which have to do with the fact that you have
|
||
severely decreased the maximum number you may have, but trust me, the
|
||
speed increase is worth it (With longintegers, and/or extended 386
|
||
registers, you can even have 16x16 fixed point, which means high
|
||
accuracy and high maximum values)
|
||
|
||
Try write a program using fixed point. It is not difficult and you will
|
||
get it perfect easily. Trust me, I'm a democoder ;-)
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Assembler
|
||
|
||
In the sample program I used one or two assembler commands that I havent
|
||
discussed with you ... here they are ...
|
||
|
||
imul value This is the same as mul, but for integer values. It
|
||
multiplies ax by the value. If the value is a word,
|
||
it returns the result in DX:AX
|
||
|
||
sal register,value This is the same as shl, but it is arithmetic,
|
||
in other words it works on integers. If you
|
||
had to shl a negative value, the result would
|
||
mean nothing to you.
|
||
|
||
rcl register,value This is the same as shl, but after you have
|
||
shifted, the value in the carry flag is placed
|
||
in the now-vacated rightmost bit. The carry
|
||
flag is set when you do an operation where the
|
||
result is greater then the upmost possible
|
||
value of the variable (usually 65535 or 32767)
|
||
eg mov ax,64000
|
||
shl ax,1 {<- Carry flag now = 1}
|
||
|
||
For more info on shifting etc, re-read tut 7, it goes into the concept
|
||
in detail.
|
||
|
||
The sample program is basically Tut 9 rewritten. To see how the
|
||
assembler stuff is working, do the following ... Go into 50 line mode
|
||
(-Much- easier to debug), then hit [Alt - D] then R. A little box with
|
||
all your registers, segments etc and their values will pop up. Move it
|
||
down to where you want it, then go back to the program screen (Hit Alt
|
||
and it's number together), and resize it so that you have both it and
|
||
the register box onscreen at once (Alt - 5 to resize) ... then use F4,
|
||
F7 and F8 to trace though the program (you know how). The current value
|
||
of the registers will always be in that box.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
Well, that is about it. The sample program may start as being a little
|
||
intimidating to some when they first look at it, just remember to read
|
||
it with tut 9, very little is different, it's just with fixed point and
|
||
a bit of assembler.
|
||
|
||
Before I forget, with Tut 13, the program crashes if you have error
|
||
checking on. This is how you sort it out :
|
||
|
||
1) Turn off error checking or
|
||
2) Make logo a pointer, and get and free the memory or
|
||
3) Read the logo directly to screen or
|
||
4) Use the {$M ......} command with various values at the top of the
|
||
program till it works.
|
||
|
||
I prefer options 3 or 2, but hey ... the problem was that the logo was
|
||
rather large (16k), and Pascal likes complaining ;-)
|
||
|
||
I am in doubt as to weather to continue doing quotes ... here is a
|
||
conversation I had with Pipsy, after the group conversation got around
|
||
to weather we were normal or not ...
|
||
|
||
Me : I'm normal.
|
||
Pipsy : No your not.
|
||
Me : Prove it.
|
||
Pipsy : Just look at your quotes in your trainers.
|
||
Me : What? You think those are weird?
|
||
Pipsy : Too weird.
|
||
Me : You mean that there is a weirdness line, and I crossed it?
|
||
Pipsy : Yes.
|
||
|
||
Bit of a conversation killer that, so we stopped there.
|
||
|
||
Anyway, this trainer won't have a quote in it ... how about a disclaimer
|
||
instead? Feel free to use it in your messages ...
|
||
|
||
------------------------------------------------------------------------
|
||
The views expressed above are mine and not Novells. In fact, I've never
|
||
worked for them in my life!
|
||
|
||
Byeeee....
|
||
- Denthor
|
||
18:57
|
||
9-9-94
|
||
|
||
|
||
The following are official ASPHYXIA distribution sites :
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen º
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º
|
||
ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º
|
||
ºC-Spam BBS º410-531-5886 ºALL º
|
||
ºPOP! º+27-12-661-1257 ºALL º
|
||
ºSoul Asylum º+358-0-5055041 ºALL º
|
||
ºWasted Image º407-838-4525 ºALL º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ
|
||
|
||
Leave me mail if you want to become an official Asphyxia BBS
|
||
distribution site.
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 15 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hello again. As you can see, this tut is very soon after the last one.
|
||
This is because of two reasons ... 1) The PCGPE ][ will be out soon, so
|
||
I thought I would make sure I have more then just four new trainers for it,
|
||
and 2) I am usually so late between tuts, I thought I would make up for it.
|
||
|
||
There is a discussion going on in Usenet, mostly saying that trainers etc.
|
||
should be written a bit more formally and none of this gay banter and
|
||
familiar language should be used. My "quotes" would definately be out ;-)
|
||
But, until I get paid for doing this (and there don't seem to be any takers
|
||
on that score), I will continue to write in this manner. My apologies to those
|
||
who dont like this, but hey, its free, what did you expect?
|
||
|
||
This trainer is on plasmas, and the sample program actually became quite large,
|
||
mostly due to the fact that there was some plasma stuff I wanted to try out.
|
||
|
||
The concept is very simple, at least for this plasma, so you shouldn't have
|
||
any problems understanding it ... AFTER you have read the text file ...
|
||
jumping straight into the source may be hazardous to your brain.
|
||
|
||
Plasmas are a great way to wow your friends by their wierd shapes and forms.
|
||
I was at one stage going to write a game where the bad guy just had two
|
||
circular plasmas instead of eyes... I am sure you will find creative and
|
||
inventive new ways of doing and using plasmas.
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
|
||
5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
|
||
us at once.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How do plasmas work?
|
||
|
||
I will only cover one type of plasma here ... a realtime plasma of course.
|
||
Other types of plasmas include a static picture with a pallette rotation...
|
||
|
||
When you get right down to it, this method of realtime plasmas is merely an
|
||
intersection of four COS waves. We get our color at a particular point by
|
||
saying :
|
||
col := costbl[one]+costbl[two]+costbl[three]+costbl[four];
|
||
|
||
The trick is getting the four indexes of that cos table array to create
|
||
something that looks nice. This is how we organise it : Have two of them
|
||
being indexes for vertical movement and two of them being indexes for
|
||
horizontal movement.
|
||
|
||
This means that by changing these values we can move along the plasma. To
|
||
draw an individual screen, we pass the values of the four to another four
|
||
so that we do not disturb the origional values. For every pixel across, we
|
||
add values to the first two indexes, then display the next pixel. For
|
||
every row down, we add values to the second two indexes. Sound complex
|
||
enough? Good, because that what we want, a complex shape on the screen.
|
||
|
||
By altering the origional four values, we can get all sorts of cool movement
|
||
and cycling of the plasma. The reason we use a cos table is as follows :
|
||
a cos table has a nice curve in the value of the numbers ... when you
|
||
put two or more together, it is possible to get circular pictures ...
|
||
circles are hard to do on a computer, so this makes it a lot easier...
|
||
|
||
Okay, now you can have a look at the source file, all I do is put the above
|
||
into practice. I did add one or two things though ...
|
||
|
||
Background : This is just a large array, with the values in the array being
|
||
added to the plasma at that pixel.
|
||
|
||
Psychadelic : This cycles through about 7000 colors instead of just rotating
|
||
through the base 256.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Clever fading
|
||
|
||
You will notice when the sample program fades in and out that the colors
|
||
all reach their destination at the same time ... it other words, they don't
|
||
all increment by one until they hit the right color then stop. When done
|
||
in that way the fading does not look as professional.
|
||
|
||
Here is how we do a step-crossfade.
|
||
|
||
Each r,g,b value can be between 0 and 64. Have the pallette we want to get
|
||
to in bob and the temporary pallette in bob2. For each step, from 0 to 63
|
||
do the following :
|
||
bob2[loop1].r:=bob[loop1].r*step/64;
|
||
|
||
That means if we are halfway through the crossfade (step=32) and the red
|
||
value is meant to get to 16, our equation looks like this :
|
||
r:=16*32/64
|
||
r=8
|
||
|
||
Which is half of the way to where it wants to be. This means all colors will
|
||
fade in/out with the same ratios... and look nicer.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Rotating the pallette
|
||
|
||
I have done this one before I think .. here it is ...
|
||
|
||
move color 0 into temp
|
||
|
||
move color 1 into color 0
|
||
move color 2 into color 1
|
||
move color 3 into color 2
|
||
and so on till color 255
|
||
|
||
move temp into color 255
|
||
|
||
And you pallette is rotating. Easy huh? Recheck tut 2 for more info on
|
||
pallette rotation
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
The text file was a bit short this time, but that is mostly because the
|
||
sample file is self explanitory. The file can however be speeded up, and
|
||
of course you can add certain things which will totally change the look
|
||
of the plasma.
|
||
|
||
As always, I am on the lookout for more ideas for future tuts, if you have
|
||
some, mail me!
|
||
|
||
No quote today, this lan doesn't encourage creative thinking ;) However,
|
||
there will be quotes in future as I have been told that some people like
|
||
them. Even Pipsy said this while we were playing Ctrl-Alt-Del (two player
|
||
game, one has to hit ctrl and alt as the other hits del, and the person
|
||
hitting the del has to do it quickly so that the computer doesnt reboot.
|
||
If the computer reboots the person who was hitting ctrl and alt has won.
|
||
I thought I was doing really badly against Pipsy until I found out that the
|
||
computer had frozen ;-))
|
||
|
||
Byeeee....
|
||
- Denthor
|
||
14:11
|
||
16-9-94
|
||
|
||
|
||
The following are official ASPHYXIA distribution sites :
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen º
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º
|
||
ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º
|
||
ºC-Spam BBS º410-531-5886 ºALL º
|
||
ºPOP! º+27-12-661-1257 ºALL º
|
||
ºSoul Asylum º+358-0-5055041 ºALL º
|
||
ºWasted Image º407-838-4525 ºALL º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ
|
||
|
||
Leave me mail if you want to become an official Asphyxia BBS
|
||
distribution site.
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 16 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hi there. This trainer is on the scaling of an arbitrary sized bitmap to
|
||
screen in two dimensions. The sample program seems to work quite quickly,
|
||
and the code is document. The scaling procedure is however totally in
|
||
assembler ... hopefully this won't cause to many problems.
|
||
|
||
EzE has released a trainer! It is on the speeding up of 3D for normal 3D
|
||
and for virtual worlds. Check it out, it is quite good (even though I get
|
||
a bit of ribbing in his quote ;-)) It will be in PCGPE ][, to be released
|
||
shortly.
|
||
|
||
I have set up a mailserver (that doesn't seem to work all the time, but
|
||
the ones that miss I post manually). It works like this :
|
||
|
||
Send mail to denthor@beastie.cs.und.ac.za with the subject line :
|
||
request-list ... it will automatically mail you back with a list of
|
||
subject lines with which you can grab certain files. You will then mail me
|
||
with the subject line of a specific file and it will send you a uuencoded
|
||
version of that file automatically. Cool, huh?
|
||
|
||
Remember, no more mail to smith9@batis.bis.und.ac.za, send it all to
|
||
denthor@beastie.cs.und.ac.za ! Thanks.
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
|
||
5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
|
||
us at once.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ What is scaling?
|
||
|
||
I think that most of you know this one already, but here goes. Let us say
|
||
you have a picture (10x10 pixels) and you want to draw it to a different
|
||
size (say 5x7 pixel), the process of altering the picture to fit into the
|
||
new size is called scaling. Scaling only works on rectangular areas.
|
||
|
||
With scaling to can easily strech and shrink your bitmaps.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Okay, so how do we code it?
|
||
|
||
Right. The way I am going to do scaling is as follows :
|
||
|
||
For the horizontal area, I am going to calculate a certain step value. I
|
||
will then trace along the bitmap, adding this step to my position, and
|
||
placing the nearest pixel on to the screen. Let me explain this simpler ...
|
||
|
||
Let us say I have a 10 pixel wide bitmap. I want to squish it into 5 pixels.
|
||
Along the bitmap, I would draw every second pixel to screen. In ascii :
|
||
|
||
1234567890 13579
|
||
+--------+ +---+
|
||
| | | |
|
||
| bitmap | | |dest
|
||
| | | |
|
||
+--------+ +---+
|
||
|
||
As you can see, by stepping through every second pixel, I have shrunk the
|
||
bitmap to a width of 5 pixels.
|
||
|
||
The equation is as follows :
|
||
|
||
step = origionalwidth / wantedwidth;
|
||
|
||
Let us say we have a 100 pixel wide bitmap, which we want to get to 20 pixels.
|
||
|
||
step = 100 / 20
|
||
step = 5
|
||
|
||
If we draw every fifth pixel from the origional bitmap, we have scaled it down
|
||
correctly! This also works for all values, if step is of type real.
|
||
|
||
We also find the step for the height in the same way.
|
||
|
||
Our horizontal loop is as follows :
|
||
|
||
For loop1:=1 to wantedwidth do BEGIN
|
||
putpixel (loop1,height,bitmap[round (curpos)],vga);
|
||
curpos:=curpos+xstep;
|
||
END;
|
||
|
||
And the vertical loop is much the same. Easy huh? So east in fact, I wrote the
|
||
procedure in pure assembler for you ;-) ... don't worry, it's commented.
|
||
|
||
In the sample program, instead of using reals I have used fixed point math.
|
||
Refer to tut 14 if you have any hassles with fixed point, it is fairly
|
||
straightforward.
|
||
|
||
I also use psuedo 3-d perspective transforms to get the positions smooth...
|
||
after Tut8, this should be a breeze.
|
||
|
||
There are no new commands in the assembler for you, so you should get by with
|
||
what you learned in tut7/8 ... whew! A lot of back referencing there ;) We
|
||
really are building on our knowledge :)
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
Well, that is about it. As you can see the concept is easy, and in fact
|
||
fairly obvious, but that didn't stop me from having to sit down with a
|
||
pencil and a piece of paper a few months ago and puzzle it out ;-)
|
||
|
||
I have a lot of work ahead of me for a while, so this may be the last
|
||
trainer for a few months ... unless I can find some free time available.
|
||
So please be patient!
|
||
|
||
|
||
[ "Sir! My computer has just gone haywire!"
|
||
"What?" shouts the CO. "That is a multimilliondollar machine!
|
||
find out what's wrong! This is a critical time lieutenant!"
|
||
"Yes sir"
|
||
The young lieutenant furiously types away at the keyboard, but
|
||
the machine totally ignores her.
|
||
"What is going on, soldier?"
|
||
"I don't know sir! It is just doing totally arbitrary things
|
||
after it's assigned tasks are completed. In the computer world
|
||
this is known as Denthorisms."
|
||
The computer starts to make random beeps, and prints out a payroll
|
||
program.
|
||
"Get it working NOW soldier"
|
||
The lieutenant ignores him, and contines typing. She gets partial
|
||
control of the system, she can run programs, but the computer is
|
||
continually running arb tasks in the background. One of the
|
||
techhies who have gathered behing her suddenly cries "Hey! It's
|
||
accessing the missile codes! It wants to launch them!"
|
||
The typing gathers speed, but to no avail. Another techhie says
|
||
"I could disconnect the computer from the link, but that would take
|
||
hours! And this thing will have the codes in under five minutes
|
||
at the speed it's going!"
|
||
A smile forms on the lieutanants face, and she leans back in her chair.
|
||
"What the hell are you doing?" yells the CO. "Why have you stopped?"
|
||
Again ignoring him, the lieutenant instead turns to the techhie. "Go
|
||
disconnect the machine, I know how to get you the time you need."
|
||
"How on earth will you do that? The machines going at top speed!"
|
||
She smiles again, leans forward, types in three letters and hits the
|
||
carriage return. The computer grinds to a halt.
|
||
The smile breaks into a grin. "Maybe it _does_ have it's uses after
|
||
all."
|
||
]
|
||
- Grant Smith
|
||
15:30
|
||
23-9-94
|
||
|
||
Byeeeee.....
|
||
|
||
The following are official ASPHYXIA distribution sites :
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen º
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º
|
||
ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º
|
||
ºC-Spam BBS º410-531-5886 ºALL º
|
||
ºPOP! º+27-12-661-1257 ºALL º
|
||
ºSoul Asylum º+358-0-5055041 ºALL º
|
||
ºWasted Image º407-838-4525 ºALL º
|
||
ºReckless Life º351-01-716 67 58ºALL º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ
|
||
|
||
Leave me mail if you want to become an official Asphyxia BBS
|
||
distribution site.
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 17 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hi there everybody. It's a new year, but the parties are over and it's time
|
||
to get coding again!
|
||
|
||
My mailserver died. Various sysadmins decided it was time to upgrade the
|
||
OS, and wound up nuking the hard drive :-( ... this means that request-list
|
||
is not working at the moment, and I have probably lost lots of mail.
|
||
|
||
denthor@beastie.cs.und.ac.za is still the account to write to, and
|
||
hopefully the mailserver will be back up in the near future.
|
||
|
||
There are various C/C++ conversions of my trainer, best of which seem to be
|
||
those by Snowman ... he runs through the text files with C++ updates (and
|
||
seems to point out my previous mistakes with glee ;-), as well is giving a
|
||
fully documented C++ conversion of the source ... very nice stuff.
|
||
|
||
Also, my trainers are being put on a World Wide Web site ... it is still
|
||
under construction, but go to http://www.cit.gu.edu.au/~rwong
|
||
my site is at http://goth.vironix.co.za/~denthor ... it is currently pretty
|
||
awful, anyone want to write a nice one for me? ;)
|
||
|
||
I have just about finished Asphyxia's new game, I will let you all know
|
||
when it is completed.
|
||
|
||
Tut 16 dies with large bitmaps ... the way to sort this out is to decrease
|
||
the accuracy of the fixed point from 256 to 128 ... then you can have
|
||
bitmaps up to 512 pixels wide. I will be putting an updated scale routine
|
||
in the gfx4.pas unit.
|
||
|
||
This tutor is on a few demo effects (pixel morphs and static) ... after
|
||
this one, I will go on to more theory ... perhaps some more 3d stuff, such
|
||
as gourad shading etc. Comments?
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
|
||
5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
|
||
us at once.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Pixel Morphing
|
||
|
||
Have you ever lain down on your back in the grass and looked up at the
|
||
cloudy sky? If you have, you have probably seen the clouds move together
|
||
and create wonderful shapes ... that cloud plus that cloud together make a
|
||
whale ... a ship ... a face etc.
|
||
|
||
We can't quite outdo mother nature, but we can sure give it a shot. The
|
||
effect I am going to show you is where various pixels at different starting
|
||
points move together and create an overall picture.
|
||
|
||
The theory behind it is simple : Each pixel has bits of data associated
|
||
with it, most important of which is as follows :
|
||
|
||
This is my color
|
||
This is where I am
|
||
This is where I want to be.
|
||
|
||
The pixel, keeping it's color, goes from where it is to where it wants to
|
||
be. Our main problem is _how_ it moves from where it is to where it wants
|
||
to be. A obvious approach would be to say "If it's destination is above it,
|
||
decrement it's y value, if the destination is to the left, decrement it's x
|
||
value and so on."
|
||
|
||
This would be bad. The pixel would only ever move at set angles, as you can
|
||
see below :
|
||
|
||
Dest O-----------------\
|
||
\ <--- Path
|
||
\
|
||
\
|
||
O Source
|
||
|
||
Doesn't look very nice, does it? The pixels would also take different times
|
||
to get to their destination, whereas we want them to reach their points at
|
||
the same time, ie :
|
||
|
||
Dest 1 O-------------------------------O Source 1
|
||
Dest 2 O-----------------O Source 2
|
||
|
||
Pixels 1 and 2 must get to their destinations at the same time for the best
|
||
effect. The way this is done by defining the number of frames or "hops"
|
||
needed to get from source to destination. For example, we could tell pixel
|
||
one it is allowed 64 hops to get to it's destination, and the same for
|
||
point 2, and they would both arrive at the same time, even though pixel 2
|
||
is closer.
|
||
|
||
The next question, it how do we move the pixels in a straight line? This is
|
||
easier then you think...
|
||
|
||
Let us assume that for each pixel, x1,y1 is where it is, and x2,y2 is where
|
||
it wants to be.
|
||
|
||
(x2-x1) = The distance on the X axis between the two points
|
||
(y2-y1) = The distance on the Y axis between the two points
|
||
|
||
If we do the following :
|
||
|
||
dx := (x2-x1)/64;
|
||
|
||
we come out with a value in dx wich is very useful. If we added dx to x1 64
|
||
times, the result would be x2! Let us check...
|
||
|
||
dx = (x2-x1)/64
|
||
dx*64 = x2-x1 { Multiply both sides by 64 }
|
||
dx*64+x1 = x2 { Add x1 to both sides }
|
||
|
||
This is high school math stuff, and is pretty self explanitory. So what we
|
||
have is the x movement for every frame that the pixel has to undergo. We
|
||
find the y movement in the same manner.
|
||
|
||
dy := (y2-y1)/64;
|
||
|
||
So our program is as follows :
|
||
|
||
Set x1,y1 and x2,y2 values
|
||
dx:= (x2-x1)/64;
|
||
dy:= (y2-y1)/64;
|
||
|
||
for loop1:=1 to 64 do BEGIN
|
||
putpixel (x1,y1)
|
||
wait;
|
||
clear pixel (x1,y1);
|
||
x1:=x1+dx;
|
||
y1:=y1+dy;
|
||
END;
|
||
|
||
If there was a compiler that could use the above pseudocode, it would move
|
||
the pixel from x1,y1 to x2,y2 in 64 steps.
|
||
|
||
So, what we do is set up an array of many pixels with this information, and
|
||
move them all at once ... viola, we have pixel morphing! It is usually best
|
||
to use a bitmap which defines the color and destination of the pixels, then
|
||
randomly scatter them around the screen.
|
||
|
||
Why not use pixel morphing on a base object in 3d? It would be the work of
|
||
a moment to add in a Z axis to the above.
|
||
|
||
The sample program uses fixed point math in order to achieve high speeds,
|
||
but it is basically the above algorithm.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Static
|
||
|
||
A static screen was one of the first effects Asphyxia ever did. We never
|
||
actually released it because we couldn't find anywhere it would fit. Maybe
|
||
you can.
|
||
|
||
The easiest way to get a sreen of static is to tune your TV into an unused
|
||
station ... you even get the cool noise effect too. Those people who build
|
||
TV's really know how to code ;-)
|
||
|
||
For us on a PC however, it is not as easy to generate a screen full of
|
||
static (unless you desperately need a new monitor)
|
||
|
||
What we do is this :
|
||
|
||
Set colors 1-16 to various shades of grey.
|
||
Fill the screen up with random pixels between colors 1 and 16
|
||
Rotate the pallette of colors 1 to 16.
|
||
|
||
That's it! You have a screenfull of static! To get two images in one static
|
||
screen, all you need to do is fade up/down the specific colors you are
|
||
using for static in one of the images.
|
||
|
||
A nice thing about a static screen is that it is just pallette rotations
|
||
... you can do lots of things in the foreground at the same time (such as a
|
||
scroller).
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
Well, that is about it ... as I say, I will be doing more theory stuff in
|
||
future, as individual demo effects can be thought up if you know the base
|
||
stuff.
|
||
|
||
Note the putpixel in this GFX3.PAS unit ... it is _very_ fast .. but
|
||
remember, just calling a procedure eats clock ticks... so imbed putpixels
|
||
in your code if you need them. Most of the time a putpixel is not needed
|
||
though.
|
||
|
||
PCGPE ][ will be out on the 10th of Feburary. All the new tutors will be on
|
||
it (if you aren't reading this from it right now! ;-) ... grab a copy of
|
||
it, it is a very useful ting to have handy.
|
||
|
||
I have found out that these tutors have been distributed inside paper
|
||
magazines ... please remember that Denthor and Asphyxia retain full
|
||
copyright to the series (as mentioned earlier in the series), and if you
|
||
want to use a version in a magazine, CONTACT ME FIRST ... I will probably
|
||
also modify it/cut out various unneccesary things ... other then that, you
|
||
must not alter the files without my permission, or at least leave a copy of
|
||
the origional with the update. Maybe I could even start up a nice column
|
||
for some magazine or other :)
|
||
|
||
Sorry 'bout that, but it had to be said ...
|
||
|
||
I am writing a column for the Demuan list, a Florida-based electronic
|
||
magazine ... pick it up off ftp.eng.ufl.edu ... I have written various
|
||
articles, all bordering on quote-like design.
|
||
|
||
There are more BBS's to be added to the list at the end, but I don't have
|
||
them here... this tut has taken long enough ;-)
|
||
|
||
Byeeeee....
|
||
- Denthor
|
||
|
||
The following are official ASPHYXIA distribution sites :
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen º
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º
|
||
ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º
|
||
ºC-Spam BBS º410-531-5886 ºALL º
|
||
ºPOP! º+27-12-661-1257 ºALL º
|
||
ºSoul Asylum º+358-0-5055041 ºALL º
|
||
ºWasted Image º407-838-4525 ºALL º
|
||
ºReckless Life º351-01-716 67 58ºALL º
|
||
ºMach 5 BBS º+1 319-355-7336 ºALL º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ
|
||
|
||
Leave me mail if you want to become an official Asphyxia BBS
|
||
distribution site.
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 18 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Welcome back! I know, I know, you all all shocked that this tut is out so
|
||
soon after the last one, but the reason for this is that I want to have Tut
|
||
20 out by the time PCGPE ][ is released. I probably won't get that far, but
|
||
I'll try! ;)
|
||
|
||
This tut is on file packing, and putting everything into one executeable
|
||
file. For tut 19, I am thinking of doing a bit more on explaining
|
||
assembler, and perhaps demonstrating with a fire effect or something.
|
||
|
||
My mailserver is back up, thanks to Nobody (that's his handle). You write
|
||
to denthor@beastie.cs.und.ac.za with the subject line request-list. The
|
||
mailserver checks each incoming letter for this subject line, and if it
|
||
finds one of the specific strings, it mails you back a certain file. I
|
||
never get to see these messages! If you want to mail me personally, give
|
||
your message a unique subject name! Anyway, you can request all the tuts
|
||
through this mailserver.
|
||
|
||
I hope you are all subscribed to the Demuan List! If not, ftp it off
|
||
ftp.eng.ufl.edu every sunday. I am writing a "humor" column there until
|
||
someone can figure out something else I could write ;-).
|
||
|
||
Pipsy wants mail! She is at cowan@beastie.cs.und.ac.za and wants to chat :)
|
||
Go on, mail her. The co-founder of ctrl-alt-del, she is also a good
|
||
graphics coder.
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
|
||
5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
|
||
us at once.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Loading a PCX file
|
||
|
||
This is actually quite easy. The PCX file is divided into three sections,
|
||
mainly a 128 byte header, a data section, and a 768 byte pallette.
|
||
|
||
You can usually ignore the 128 byte header, but here it is :
|
||
|
||
0 Manufacturer 10 = ZSoft .PCX file
|
||
1 Version
|
||
2 Encoding
|
||
3 Bits Per Pixel
|
||
4 XMin, Ymin, XMax, YMax (2 bytes each)
|
||
12 Horizontal Resolution (2 bytes)
|
||
14 Verticle Resolution (2 bytes)
|
||
16 Color pallette setting (48 bytes)
|
||
64 Reserved
|
||
65 Number of color planes
|
||
66 Bytes per line (2 bytes)
|
||
68 1 = Color 2 = Grayscale (2 bytes)
|
||
70 Blank (58 bytes)
|
||
|
||
That makes 128 bytes.
|
||
|
||
The pallette file, which is 768 bytes, is situated at the very end of the
|
||
PCX file. The 769'th byte back should be the decimal 12, which indicates
|
||
that a VGA color pallette is to follow.
|
||
|
||
There is one thing that we have to do to get the pallette correct in VGA ...
|
||
the PCX pallette values for R,G,B are 0 to 255 respectively. To convert this
|
||
to our standard (VGA) pallette, we must divide the R,G,B values by 4, to get
|
||
them into a range of 0 to 63.
|
||
|
||
Actually decoding the image is very simple. Starting after the 128 byte
|
||
header, we read a byte.
|
||
|
||
If the top two bits of this byte are not set, we dump the value to the screen.
|
||
|
||
We check bits as follows :
|
||
|
||
if ((temp and $c0) = $c0) then ...(bits are set)... else ...(bits are not set)
|
||
|
||
C0 in hex = 11000000 in binary = 192 in decimal
|
||
|
||
Let's look at that more closely...
|
||
|
||
temp and c0h
|
||
temp and 11000000b
|
||
|
||
That means, when represented in bit format, both corresponding bits have
|
||
to be set to one for the result to be one.
|
||
|
||
0 and 0 = 0 1 and 0 = 0 0 and 1 = 0 1 and 1 = 1
|
||
|
||
In the above case then, both of the top two bits of temp have to be set for
|
||
the result to equal 11000000b. If it does not equal that, the top two bits
|
||
are not both set, and we can put the pixel.
|
||
|
||
So
|
||
|
||
if ((temp and $c0) = $c0) then BEGIN
|
||
END else BEGIN
|
||
putpixel (screenpos,0,temp,vga);
|
||
inc (screenpos);
|
||
END;
|
||
|
||
If the top two bits _are_ set, things change. The bottom six bits become
|
||
a loop counter, which the next byte is repeated.
|
||
|
||
if ((temp and $c0) = $c0) then BEGIN
|
||
{ Read in next byte, temp2 here.}
|
||
for loop1:=1 to (temp and $3f) do BEGIN
|
||
putpixel (screenpos,0,temp2,vga);
|
||
inc (screenpos);
|
||
END;
|
||
END else BEGIN
|
||
putpixel (screenpos,0,temp,vga);
|
||
inc (screenpos);
|
||
END;
|
||
|
||
There is our PCX loader. You will note that by and'ing temp by $3f, I am
|
||
and'ing it by 00111111b ... in other words, clearing the top two bits.
|
||
|
||
The sample program has the above in assembler, but it is the same procedure...
|
||
and you can read tut 19 for more info on how to code in assembler.
|
||
|
||
In the sample I assume that the pic is 320x200, with a maximum size of 66432
|
||
bytes.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ File packing
|
||
|
||
The question is simple .. how do I get all my files into one executeable?
|
||
Having many small data files can start to look unprofessional.
|
||
|
||
An easy way to have one .exe and one .dat file when dealing with many
|
||
cel's etc. is easy .... you would alter your load procedure, which looks
|
||
as follows :
|
||
|
||
VAR temp : Array [1..5,1..256] of byte;
|
||
Procedure Init;
|
||
BEGIN
|
||
loadcel ('pic1.cel',temp[1]);
|
||
loadcel ('pic2.cel',temp[2]);
|
||
loadcel ('pic3.cel',temp[3]);
|
||
loadcel ('pic4.cel',temp[4]);
|
||
loadcel ('pic5.cel',temp[5]);
|
||
END;
|
||
|
||
For one complile you would do this :
|
||
|
||
VAR temp : Array [1..5,1..256] of byte;
|
||
Procedure Init;
|
||
VAR f:File;
|
||
BEGIN
|
||
loadcel ('pic1.cel',temp[1]);
|
||
loadcel ('pic2.cel',temp[2]);
|
||
loadcel ('pic3.cel',temp[3]);
|
||
loadcel ('pic4.cel',temp[4]);
|
||
loadcel ('pic5.cel',temp[5]);
|
||
assign (f,'pic.dat');
|
||
rewrite (f,1);
|
||
blockwrite (f,temp,sizeof(temp));
|
||
close (f);
|
||
END;
|
||
|
||
From then on, you would do :
|
||
|
||
VAR temp : Array [1..5,1..256] of byte;
|
||
Procedure Init;
|
||
VAR f:File;
|
||
BEGIN
|
||
assign (f,'pic.dat');
|
||
reset (f,1);
|
||
blockread (f,temp,sizeof(temp));
|
||
close (f);
|
||
END;
|
||
|
||
This means that instead of five data files, you now have one! You have also
|
||
stripped the 800 byte cel header too :) ... note that this will work for any
|
||
form of data, not just cel files.
|
||
|
||
The next logical step is to include this data in the .exe file, but the
|
||
question is how? In an earlier tutorial, I converted my data file to
|
||
constants and placed it inside my main program. This is not good mainly
|
||
because of space restrictions ... you can only have so many constants, and
|
||
what if your data file is two megs big?
|
||
|
||
Attached with this tutorial is a solution. I have written a program that
|
||
combines your data files with your executeable file, no matter how big
|
||
the data is. The only thing you have to worry about is a small change in
|
||
your data loading methods. Lets find out what.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Using the file packer
|
||
|
||
Normally you would load your data as follows :
|
||
|
||
Procedure Init;
|
||
BEGIN
|
||
loadcel ('bob.bob',temp);
|
||
loadpcx ('den.pcx',VGA); { Load a PCX file }
|
||
loaddat ('data.dat',lookup); { Load raw data into lookup }
|
||
END;
|
||
|
||
Easy, hey? Now, using the file packer, you would change this to :
|
||
|
||
USES fpack;
|
||
Procedure Init;
|
||
BEGIN
|
||
total := 3;
|
||
infodat[1] := 'bob.bob';
|
||
infodat[2] := 'den.pcx';
|
||
infodat[3] := 'data.dat';
|
||
loadcel (1,temp);
|
||
loadpcx (2,VGA);
|
||
loaddat (3,lookup);
|
||
END;
|
||
|
||
Not too difficult? Now, this is still using the normal data files on your
|
||
hard drive. You would then run PACK.EXE, select the program's .exe as the
|
||
base, then select "bob.bob", "den.pcx" and "data.dat", in order (1, 2, 3).
|
||
Hit "c" to contine, and it will combine the files. Your programs .exe file
|
||
will be able to run independantly of the separate data files on disk,
|
||
because the data files are imbedded with the .exe.
|
||
|
||
Let us take a closer look at the load procedures. Normally a load procedure
|
||
would look as follows :
|
||
|
||
Procedure LoadData (name:string; p:pointer);
|
||
VAR f:file;
|
||
BEGIN
|
||
assign (f,name);
|
||
reset (f,1);
|
||
blockread (f,p^,filesize(f);
|
||
close (f);
|
||
END;
|
||
|
||
In FPack.pas, we do the following :
|
||
|
||
Function LoadData (num:integer; p:pointer):Boolean;
|
||
VAR f:file;
|
||
BEGIN
|
||
If pack then BEGIN
|
||
assign (f,paramstr(0));
|
||
reset (f,1);
|
||
seek (f,infopos[num]);
|
||
blockread (f, p^, infopos[num+1]-infopos[num]);
|
||
close (f);
|
||
END else BEGIN
|
||
assign (f,infodat[num]);
|
||
reset (f,1);
|
||
blockread (f, p^, filesize (f));
|
||
close (f);
|
||
END;
|
||
END;
|
||
|
||
As you can see, we just have two special cases depending on weather or not
|
||
the .exe file has been packed yet.
|
||
|
||
NOTE : After you have packed the file, you CAN NOT pklite it. You can
|
||
however pklite the .exe _before_ you run pack.exe ... in other
|
||
words, you can not use pklite to try pack your data files.
|
||
|
||
PACK.EXE does have a limitation ... you can only pack 24 data files together.
|
||
If you would like it to do more, mail me ... It should be easy to increase the
|
||
number.
|
||
|
||
In the sample program, FINAL.EXE is the same as temp.pas, except it has
|
||
it's PCX embedded inside it. I ran pack2.exe, selected final.exe and
|
||
eye.pcx, hit "C", and there it was. You will notice that eye.pcx is not
|
||
included in the directory ... it is now part of the exe!
|
||
|
||
eye.pcx was draw by Gary Morton of iCANDi Design. The other pcx is an old
|
||
one draw by Fubar.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
Well, that's about it for this trainer... next one (as I have mentioned
|
||
twice already ;) will be on assembler, with a flame routine thrown in.
|
||
|
||
Any good html programmers out there? My web page really needs help ;-)
|
||
|
||
As soon as I figure out how, I will also be creating a mailing list, in
|
||
which people with internet addresses will be able to get all new trainers
|
||
dilivered directly into their mailbox's. I hope to announce something in
|
||
tut 20.
|
||
|
||
This tut has been a bit of a departure from normal tuts ... aside from the
|
||
PCX loading routines, the rest has been "non programming" oriented ...
|
||
don't worry, next weeks one will be back to normal.
|
||
|
||
|
||
Byeeeee....
|
||
- Denthor
|
||
|
||
The following are official ASPHYXIA distribution sites :
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen º
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º *Moving*
|
||
ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º *Moving*
|
||
ºC-Spam BBS º410-531-5886 ºALL º
|
||
ºPOP! º+27-12-661-1257 ºALL º
|
||
ºSoul Asylum º+358-0-5055041 ºALL º
|
||
ºWasted Image º407-838-4525 ºALL º
|
||
ºReckless Life º351-01-716 67 58ºALL º
|
||
ºMach 5 BBS º+1 319-355-7336 ºALL º
|
||
ºHouse of Horror º+1 513-734-6470 ºALL º
|
||
ºZero Level º+39 6-810-9934 ºALL º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ
|
||
|
||
Leave me mail if you want to become an official Asphyxia BBS
|
||
distribution site.
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 19 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hi there. As promised in Tut 18, this trainer is on assembler. For those
|
||
people who already know assembler quite well, this tut is also on the flame
|
||
effect.
|
||
|
||
Okay, here is the total list of ways to get my trainers :
|
||
|
||
http://goth.vironix.co.za/~denthor (WWW)
|
||
ftp.eng.ufl.edu pub/msdos/demos/code/graph/tutor (FTP)
|
||
denthor@beastie.cs.und.ac.za Subject : request-list (EMAIL)
|
||
|
||
As well as the BBS numbers shown at the end ... I will add a few ftp sits
|
||
to that list (x2ftp.oulu.fi etc.)
|
||
|
||
Tut 20? How about 3d shading, hidden surface removal etc? Mail me :)
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
|
||
5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
|
||
us at once.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Assembler - the short version
|
||
|
||
Okay, there are many assembler trainers out there, many of which are
|
||
probably better then this one. I will focus on the areas of assembler that
|
||
I find important ... if you want more, go buy a book (go for the Michael
|
||
Abrash ones), or scour the 'net for others.
|
||
|
||
First, let us start off with the basic set up of an assembler program.
|
||
|
||
DOSSEG
|
||
|
||
This tells your assembler program to order your segments in the same manner
|
||
that high level languages do.
|
||
|
||
.MODEL <MODEL>
|
||
|
||
<MODEL> can be : Tiny Code + Data < 64k (Can be made a COM file)
|
||
Small Code < 64k Data < 64k
|
||
Medium Code > 64k Data < 64k
|
||
Compact Code < 64k Data > 64k
|
||
Large Code > 64k Data > 64k
|
||
Huge Arrays > 64k
|
||
|
||
.286
|
||
|
||
Enable 286 instructions ... can be .386 ; .386P etc.
|
||
|
||
.STACK <size>
|
||
|
||
<size> will be the size of your stack. I usually use 200h
|
||
|
||
.DATA
|
||
|
||
Tells the program that the data is about to follow. (Everything after this
|
||
will be placed in the data segment)
|
||
|
||
.CODE
|
||
|
||
Tells the program that the code is about to follow. (Everything after this
|
||
will be placed in the code segment)
|
||
|
||
START :
|
||
|
||
Tells the program that this is where the code begins.
|
||
|
||
END START
|
||
|
||
Tells the program that this is where the code ends.
|
||
|
||
To compile and run an assembler file, we run
|
||
tasm bob
|
||
tlink bob
|
||
|
||
I personally use tasm, you will have to find out how your assembler works.
|
||
|
||
Now, if we ran the above file as follows :
|
||
|
||
DOSSEG
|
||
.MODEL SMALL
|
||
.286
|
||
.STACK 200h
|
||
.DATA
|
||
.CODE
|
||
|
||
START
|
||
END START
|
||
|
||
You would think that is would just exit to dos immediately, right? Wrong.
|
||
You have to specifically give dos back control, by doing the following :
|
||
|
||
START
|
||
mov ax,4c00h
|
||
int 21h
|
||
END START
|
||
|
||
Now if you compiled it, it would run and do nothing.
|
||
|
||
Okay, let us kick off with registers.
|
||
|
||
Firstly : A bit is a value that is either 1 or 0
|
||
|
||
This is obviously quite limited, but if we start counting in them, we can
|
||
get larger numbers. Counting with ones and zeros is known as binary, and we
|
||
call it base 2. Counting in normal decimal is known as base 10, and
|
||
counting in hexidecimal is known as base 16.
|
||
|
||
Base 2 (Binary) Base 10 (Decimal) Base 16 (Hexidecimal)
|
||
0 0 0
|
||
1 1 1
|
||
10 2 2
|
||
11 3 3
|
||
100 4 4
|
||
101 5 5
|
||
110 6 6
|
||
111 7 7
|
||
1000 8 8
|
||
1001 9 9
|
||
1010 10 A
|
||
1011 11 B
|
||
1100 12 C
|
||
1101 13 D
|
||
1110 14 E
|
||
1111 15 F
|
||
|
||
As you can see, you need four bits to count up to 15, and we call this a
|
||
nibble. With eight bits, we can count up to 255, and we call this a byte.
|
||
With sixteen bits, we can count up to 65535, and we call this a word. With
|
||
thirty two bits, we can count up to lots, and we call this a double word. :)
|
||
|
||
A quick note : Converting from binary to hex is actually quite easy. You
|
||
break up the binary into groups of four bits, starting on the right, and
|
||
convers these groups of four to hex.
|
||
|
||
1010 0010 1111 0001
|
||
= A 2 F 1
|
||
|
||
Converting to decimal is a bit more difficult. What you do, is you multiply
|
||
each number by it's base to the power of it's index ...
|
||
|
||
A2F1 hex
|
||
= (A*16^3) + (2*16^2) + (F*16^1) + (1*16^0)
|
||
= (10*4096) + (2*256) + (15*16) + (1)
|
||
= 40960 + 512 + 240 + 1
|
||
= 41713 decimal
|
||
|
||
The same system can be used for binary.
|
||
|
||
To convert from decimal to another base, you divide the decimal value by the
|
||
desired base, keeping a note of the remainders, and then reading the results
|
||
backwards.
|
||
|
||
16 | 41713
|
||
16 | 2607 r 1 (41713 / 16 = 2607 r 1)
|
||
16 | 162 r F (2607 / 16 = 162 r 15)
|
||
16 | 10 r 2 (162 / 16 = 10 r 2)
|
||
| 0 r A (10 / 16 = 0 r 10)
|
||
|
||
Read the remainders bacckwards, our number is : A2F1 hex. Again, the same
|
||
method can be used for binary.
|
||
|
||
The reason why hex is popular is obvious ... using bits, it is impossible
|
||
to get a reasonable base 10 (decimal) system going, and binary get's unwieldly
|
||
at high values. Don't worry too much though : most assemblers (like Tasm)
|
||
will convert all your decimal values to hex for you.
|
||
|
||
You have four general purpose registers : AX, BX, CX and DX
|
||
Think of them as variables that you will always have. On a 286, these
|
||
registers are 16 bytes long, or one word.
|
||
|
||
As you know, a word consists of two bytes, and in assembler you can access
|
||
these bytes individualy. They are separated into high bytes and low bytes per
|
||
word.
|
||
|
||
High Byte | Low Byte
|
||
0000 0000 | 0000 0000 bits
|
||
[--------Word-------]
|
||
|
||
The method of access is easy. The high byte of AX is AH, and the low byte is
|
||
AL ... you can also access BH, BL, CH, CL, DH and DL.
|
||
|
||
A 386 has extended registers : EAX, EBX, ECX, EDX ... you can access the
|
||
lower word normally (as AX, with bytes AH and AL), but you cannot access the
|
||
high word directly ... you must ror EAX,16 (rotate the binary value through
|
||
16 bits), after which the high word and low word swap ... do it again to
|
||
return them. Acessing EAX as a whole is no problem ... mov eax,10 ;
|
||
add eax,ebx ... these are all vaild.
|
||
|
||
Next come segments. As you have probably heard, computer memory is divided
|
||
into various 64k segments (note : 64k = 65536 bytes, sound familiar?) A
|
||
segment register points to which segment you are looking at. An offset
|
||
register points to how far into that segment you are looking. One way
|
||
of looking at it is like looking at a 2d array ... the segments are your
|
||
columns and your offsets are your rows. Segments and offsets are displayed
|
||
as Segment:Offset ... so $a000:50 would mean the fiftieth byte in segment
|
||
$a000.
|
||
|
||
The segment registers are ES, DS, SS and CS. A 386 also has FS an GS.
|
||
These values are words (0-65535), and you cannot access the high or low bytes
|
||
separately. CS points to you your code segment, and usually if you touch this
|
||
your program will explode. SS points to your stack segment, again, this
|
||
baby is dangerous. DS points to your data segment, and can be altered, if
|
||
you put it back after you use it, and don't use any global variables while
|
||
it is altered. ES is your extra segment, and you can do what you want with
|
||
it.
|
||
|
||
The offset registers are DI, SI, IP, SP, BP. Offset registers are generally
|
||
asscociated with specific segment registers, as follows :
|
||
ES:DI DS:SI CS:IP SS:SP ... On a 286, BX can be used instead of the above
|
||
offset registers, and on a 386, any register may be used. DS:BX is therefore
|
||
valid.
|
||
|
||
If you create a global variable (let's say bob), when you access that
|
||
variable, the compiler will actually look for it in the data segment.
|
||
This means that the statement :
|
||
|
||
ax = bob
|
||
could be
|
||
ax = ds:[15]
|
||
|
||
A quick note : A value may be signed or unsigned. An unsigned word has a
|
||
range from 0 to 65535. A signed word is called an integer and has a range
|
||
-32768 to 32767. With a signed value, if the leftmost bit is equal to 1,
|
||
the value is in the negative.
|
||
|
||
Next, let us have a look at the stack. Let us say that you want to save the
|
||
value in ax, use ax to do other things, then restore it to it's origional
|
||
value afterwards. This is done by utilising the stack. Have a look at the
|
||
following code :
|
||
|
||
mov ax, 50 ; ax is equal to 50
|
||
push ax ; push ax onto the stack
|
||
mov ax, 27 ; ax is equal to 27
|
||
pop ax ; pop ax off the stack
|
||
At this point, ax is equal to 50.
|
||
|
||
Remember we defined the stack to be 200h further up? This is part of the
|
||
reason we have it. When you push a value onto the stack, that value is
|
||
recorded on the stack heap (referenced by SS:SP, SP is incremented) When you
|
||
pop a value off the stack, the value is placed into the variable you are
|
||
poping it back in to, SP is decremented and so forth. Note that the computer
|
||
does not care what you pop the value back in to ...
|
||
|
||
mov ax, 50
|
||
push ax
|
||
pop bx
|
||
|
||
Would set the values of both ax and bx to 50. (there are faster ways of doing
|
||
this, pushing and poping are fairly fast though)
|
||
|
||
push ax
|
||
push bx
|
||
pop ax
|
||
pop bx
|
||
|
||
would swap the values of ax and bx. As you can see, to pop the values back
|
||
in to the origional variables, you must pop them back in the opposite
|
||
direction to which you pushed them.
|
||
|
||
push ax
|
||
push bx
|
||
push cx
|
||
|
||
pop cx
|
||
pop bx
|
||
pop ax
|
||
|
||
would result in no change for any of the registers.
|
||
|
||
When a procedure is called, all the parameters for that procedure are pushed
|
||
onto the stack. These can actually be read right off the stack, if you want
|
||
to.
|
||
|
||
As you have already seen, the mov command moves a value...
|
||
|
||
mov <dest>, <source>
|
||
|
||
Note that dest and source must be the same number of bits long...
|
||
|
||
mov ax, dl
|
||
|
||
would not work, and neither would
|
||
|
||
mov cl,bx
|
||
|
||
However, mov cx,dx
|
||
mov ax,50
|
||
mov es,ax
|
||
are all valid.
|
||
|
||
Shl I have explained before, it is where all the bits in a register are
|
||
shifted one to the left and a zero added on to the right. This is the
|
||
eqivalent of multiplying the value by two. Shr works in the opposite
|
||
direction.
|
||
|
||
Rol does the same, except that the bit that is removed from the left is
|
||
replaced on the right hand side. Ror works in the opposite direction.
|
||
|
||
div <value> divides the value in ax by value and returns the result in
|
||
al if value is a byte, placing the remainder in ah. If value is a word,
|
||
the double word DX:AX is divided by value, the result being placed in ax
|
||
and the remainder in dx. Note that this only works for unsigned values.
|
||
|
||
idiv <value> does the same as above, but for signed variables.
|
||
|
||
mul <value> If value is a byte, al is multiplied by value and the result
|
||
is stored in ax. If value is a word, ax is multiplied by value and the
|
||
result is stored in the double word DX:AX
|
||
|
||
imul <value> does the same as above, but for signed variables.
|
||
|
||
The j* commands are fairly simple : if a condition is met, jump to a certain
|
||
lable.
|
||
|
||
jz <label> Jump if zero
|
||
ja <label> Jump above (unsigned)
|
||
jg <label> Jump greater (signed)
|
||
|
||
and so forth.
|
||
|
||
An example ...
|
||
|
||
cmp ax,50 ; Compare ax to 50
|
||
je @Equal ; If they are equal, jump to label @equal
|
||
|
||
call MyProc Runs procedure MyProc and then returns to the next line of code.
|
||
|
||
Procedures are declared as follows :
|
||
|
||
MyProc proc near
|
||
ret ; Must be here to return from where it was called
|
||
MyProc endp
|
||
|
||
Variables are also easy :
|
||
|
||
bob db 50
|
||
|
||
creates a variable bob, a byte, with an initial value of 50.
|
||
|
||
bob2 dw 50
|
||
|
||
creates a variable bob2, a word, with an initial value of 50.
|
||
|
||
bob3 db 1,2,3,4,5,65,23
|
||
|
||
creates bob3, an array of 7 bytes.
|
||
|
||
bob4 db 100 dup (?)
|
||
|
||
creates bob4, an array of 100 bytes, with no starting value.
|
||
|
||
Go back and look at tut 7 for a whole lot more assembler commands, and get
|
||
some sort of reference guide to help you out with others. I personally use
|
||
the Norton Guides help file to program assembler.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Fire Routines
|
||
|
||
To demonstrate how to write an assembler program, we will write a fire
|
||
routine in 100% assembler. The theory is simple...
|
||
|
||
Set the pallette to go from white to yellow to red to blue to black.
|
||
Create a 2d array representing the screen on the computer.
|
||
Place high values at the bottom of the array (screen)
|
||
for each element, do the following :
|
||
Take the average of the four elements under it
|
||
|
||
* Current element
|
||
123
|
||
4 Other elements
|
||
Get the average of the four elements, and place the result in the current
|
||
element.
|
||
Repeat
|
||
|
||
Easy, no? I first saw a fire routine in the Iguana demo, and I just had to
|
||
do one ;) ... it looks very effective.
|
||
|
||
With the sample file, I have created a batch file, make.bat ... it basically
|
||
says :
|
||
tasm fire
|
||
tlink fire
|
||
|
||
So to build and run the fire program, type :
|
||
make
|
||
fire
|
||
|
||
The source file is commented quite well, so there shouldn't be any problems.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
As you can see, the sample program is in 100% assembler. For the next tut
|
||
I will return to Pascal, and hopefully your new found assembler skills will
|
||
help you there too.
|
||
|
||
|
||
|
||
Byeeeee....
|
||
- Denthor
|
||
|
||
The following are official ASPHYXIA distribution sites :
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ»
|
||
ºBBS Name ºTelephone No. ºOpen º
|
||
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹
|
||
ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º
|
||
ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º
|
||
ºC-Spam BBS º410-531-5886 ºALL º
|
||
ºPOP! º+27-12-661-1257 ºALL º
|
||
ºSoul Asylum º+358-0-5055041 ºALL º
|
||
ºWasted Image º407-838-4525 ºALL º
|
||
ºReckless Life º351-01-716 67 58ºALL º
|
||
ºMach 5 BBS º+1 319-355-7336 ºALL º
|
||
ºHouse of Horror º+1 513-734-6470 ºALL º
|
||
ºZero Level º+39 6-810-9934 ºALL º
|
||
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ
|
||
|
||
Leave me mail if you want to become an official Asphyxia BBS
|
||
distribution site.
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 20 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hi all! It has been a _long_ time since my last trainer (as I am sure many
|
||
of you have noticed) A lot has happened between now and the last trainer...
|
||
but for once I won't bore you with the details ;) I do have a full time job
|
||
though, coding C++ applications.
|
||
|
||
I have taken over the production of the PCGPE from Mark Feldman. He is
|
||
mailing all the articles written so far, and as soon as I get them I will
|
||
get to work on releasing the PCGPE II. Mark is working on the Windows GPE.
|
||
|
||
This trainer is on 3d hidden face removal and face sorting. I was going to
|
||
add shading, but that can wait until a later trainer. For conveniance I
|
||
will build on the 3d code from tut 16(?). The maths for face removal is a
|
||
bit tricky, but just think back to your old High School trig classes.
|
||
|
||
I have noticed that in my absence, one or two people have started their own
|
||
trainer series. Read Hornet DemoNews for a great column by Trixter covering
|
||
some of the more tricky demo effects.
|
||
|
||
Well, on with the trainer!
|
||
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during varsity). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
|
||
5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
|
||
us at once.
|
||
|
||
NB : If you are a representative of a company or BBS, and want ASPHYXIA
|
||
to do you a demo, leave mail to me; we can discuss it.
|
||
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
|
||
quite lonely and want to meet/help out/exchange code with other demo
|
||
groups. What do you have to lose? Leave a message here and we can work
|
||
out how to transfer it. We really want to hear from you!
|
||
|
||
http://goth.vironix.co.za/~denthor (WWW)
|
||
ftp.eng.ufl.edu pub/msdos/demos/code/graph/tutor (FTP)
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Face Sorting
|
||
|
||
There are many ways to sort faces in a 3d object. For now, I will show you
|
||
just about the easiest one of the lot.
|
||
|
||
Say you have to polygons....
|
||
|
||
------P1
|
||
|
||
------------------P2
|
||
|
||
Eye
|
||
|
||
As you can see, P1 has to be drawn before P2. The easiest way to do this is
|
||
as follows:
|
||
|
||
On startup, find the mid point of each of the polys, through the easy
|
||
equations,
|
||
x = (P2.1.x + P2.2.x + P2.3.x + p2.4.x)/4
|
||
y = (P2.1.y + P2.2.y + P2.3.y + p2.4.y)/4
|
||
z = (P2.1.z + P2.2.z + P2.3.z + p2.4.z)/4
|
||
|
||
NOTE : For a triangle you would obviously only use three points and divide
|
||
by three.
|
||
|
||
Anyway, now you have the X,Y,Z of the midpoint of the polygon. You can then
|
||
rotate this point with the others. When it comes time to draw, you can
|
||
compare the resulting Z of the midpoint, sort all of the Z items, and then
|
||
draw them from back to front.
|
||
|
||
In the sample program I use a simple bubble sort... basically, I check the
|
||
first two values against each other, and swap them if the first is bigger
|
||
then the second. I continue doing this to all the numbers until I run
|
||
through the entire list without swapping once. Bubble sorts are standard
|
||
seven computer science topics... perhaps borrow a text book to find out
|
||
more about them and other (better) sorting methods.
|
||
|
||
The above isn't perfect, but it should work 90% of the time. But it still
|
||
means that when you are drawing a cube, you have to draw all 6 sides every
|
||
frame, even though only three or so are visible. That is where hidden face
|
||
removal comes in...
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Hidden Face Removal
|
||
|
||
Pick up something square. A stiffy disk will do fine. Face it towards you,
|
||
and number all the corners from one to four in a clockwise direction.
|
||
|
||
1 +-------------+ 2
|
||
| |
|
||
| |
|
||
| |
|
||
| |
|
||
4 +-------------+ 3
|
||
|
||
Now rotate the stiffy disk on all three axese, making sure that you can
|
||
still see the front of the disk. You will notice that whenever you can see
|
||
the front of the disk, the four points are still in alphabetical order. Now
|
||
rotate it so that you can see the back of the stiffy. Your points will now
|
||
be :
|
||
|
||
2 +-------------+ 1
|
||
| |
|
||
| |
|
||
| |
|
||
| |
|
||
3 +-------------+ 4
|
||
|
||
The points are now anti-clockwise! This means, in it's simplest form, that
|
||
if you define all your poygon points in a clockwise order, when drawing you
|
||
ignore the polys that are anticlockwise. (Obviously when you define the 3d
|
||
object, you define the polygons facing away from you in an anticlockwise
|
||
order)
|
||
|
||
To find out weather a poly's points are clockwise or not, we need to find
|
||
it's normal. Here is where things start getting fun.
|
||
|
||
In school, you are told that a normal is perpendicular to the plane. In
|
||
ascii :
|
||
| Normal
|
||
|
|
||
|
|
||
--------------------------- Polygon
|
||
|
||
As you can see, the normal is at 90 degrees to the surface of the poly. We
|
||
must extend this to three dimensions for our polygons. You'll have to trust
|
||
me on that, I can't draw it in ascii :)
|
||
|
||
To find a normal, you only need three points from your poly (ABC) :
|
||
A(x0,y0,z0), B(X1,Y1,Z1), C(X2,Y2,Z2)
|
||
|
||
then the vector normal = AB^AC = (Xn,Yn,Zn) with
|
||
Xn=(y1-y0)(z0-z2)-(z1-z0)(y0-y2)
|
||
Yn=(z1-z0)(x0-x2)-(x1-x0)(z0-z2)
|
||
Zn=(x1-x0)(y0-y2)-(y1-y0)(x0-x2)
|
||
|
||
We are interested in the Z normal, so we will use the function :
|
||
normal:=(x1-x0)(y0-y2)-(y1-y0)(x0-x2);
|
||
|
||
The result is something of a sine wave when you rotate the poly in three
|
||
dimensions. A negative value means that the poly is facing you, a posotive
|
||
value means that it is pointing away.
|
||
|
||
The above means that with a mere two muls you can discount an entire poly
|
||
and not draw it. This method is perfect for "closed" objects such as cubes
|
||
etc.
|
||
|
||
I am anything but a maths teacher, so go borrow someones math book to find
|
||
out more about surface normals. Trust me, there is a lot more written about
|
||
them then you think.
|
||
|
||
An extension of calculating your normal is finding out about light-sourcing
|
||
your polygons. Watch for more information in one of the next few tutors.
|
||
|
||
|
||
A combination of the above two routines should work quite nicely in
|
||
creating 3d objects with little or no overlapping. The example file will
|
||
show you the two methods and how well they work.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
As you can see, the above was quite easy. I have a few ideas for tut 21, so
|
||
keep watch for it. Also keep an eye open for PCGPE ][ (but don't mail me
|
||
asking when it's due! I already get too many of those! ;-)
|
||
|
||
My sister got married a few days ago. The worst part was that I was forced
|
||
to cut my hair. My hair was quite long (slightly longer then when the pic
|
||
on my web page was taken), and it is all quite depressing. Anyway, the
|
||
wedding was great, so it wasn't all for nothing.
|
||
|
||
I hope to get tut 21 and possibly 22 out before christmas, but I will be on
|
||
holiday from the 18th. I will be in Cape Town sometime after christmas day
|
||
for a week or two, so if you're there I'll meet you on the cable car :-)
|
||
|
||
I wrote a quote for this tut, but I have decided I didn't like it. I'll try
|
||
do better for tut 21 ;)
|
||
|
||
Byeeeee.....
|
||
- Denthor
|
||
14-12-95
|
||
|
||
PS. I seem to have lost my list of distribution sites... could you all
|
||
re-mail me your details? Thanks.
|
||
ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
|
||
³ W E L C O M E ³
|
||
³ To the VGA Trainer Program ³ ³
|
||
³ By ³ ³
|
||
³ DENTHOR of ASPHYXIA ³ ³ ³
|
||
ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
|
||
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||
|
||
--==[ PART 21 ]==--
|
||
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Introduction
|
||
|
||
Hi there! It's been quite a long time (again) since the last tutorial ...
|
||
I'll bet some of you had given up one me ;-)
|
||
|
||
Today is my 21st birthday, so I decided it would be the perfect time to
|
||
finish up this trainer which I have been meaning to send out for weeks.
|
||
It's on texure mapping. I know, I know, I said light sourcing, then gourad,
|
||
then texture mapping, but I got enough mail (a deluge in fact ;) telling me
|
||
to do texure mapping...
|
||
|
||
I'll be using the code from Tut 20 quite extensively, so make sure you know
|
||
whats going on in there... well, on with the show!
|
||
|
||
BTW, I've improved my web page quite a bit... give it a visit, I want to
|
||
really ramp up that hit count :)
|
||
|
||
If you would like to contact me, or the team, there are many ways you
|
||
can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
|
||
on the ASPHYXIA BBS.
|
||
2) Write to : Grant Smith
|
||
P.O.Box 270 Kloof
|
||
3640
|
||
Natal
|
||
South Africa
|
||
3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
|
||
call during work hours). Call +27-31-73-2129 if you call
|
||
from outside South Africa. (It's YOUR phone bill ;-))
|
||
4) Write to denthor@goth.vironix.co.za in E-Mail.
|
||
5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
|
||
us at once.
|
||
|
||
http://www.vironix.co.za/~grants (WWW)
|
||
ftp.eng.ufl.edu pub/msdos/demos/code/graph/tutor (FTP)
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ Free Direction Texture Mapping
|
||
|
||
There are two things you should know before we begin.
|
||
|
||
Firstly, I am cheating. The texture mapping I am going to show you is not
|
||
perspective-correct, with clever divides for z-placement etc. This method
|
||
looks almost as good and is quite a bit faster too.
|
||
|
||
Secondly, you will find it all rather easy. The reason for this is that it's
|
||
all rather simple. I first made the routine by sitting down with some paper
|
||
and a pencil and had it on the machine in a few hours. A while later when
|
||
people on the net started discussing their methods, they were remarkably
|
||
similar.
|
||
|
||
Let me show you what I mean.
|
||
|
||
Let us assume you have a texture of 128x128 (a straight array of bytes
|
||
[0..127, 0..127]) which you want to map onto the side of a polygon. The
|
||
problem of course being that the polygon can be all over the place, with
|
||
one side longer then the other etc.
|
||
|
||
Our first step is to make sure we know which end is up... let me
|
||
demonstrate...
|
||
1
|
||
+
|
||
/ \
|
||
/ \
|
||
4 + + 2
|
||
\ /
|
||
\ /
|
||
+
|
||
3
|
||
|
||
Let us say that the above is the chosen polygon. We have decided that point
|
||
1 is the top left, point 3 is bottom right. This means that
|
||
1 - 2 is the top of the texture
|
||
2 - 3 is the right of the texture
|
||
3 - 4 is the bottom of the texture
|
||
4 - 1 is the left of the texture
|
||
|
||
The same polygon, but rotated :
|
||
|
||
3
|
||
+
|
||
/ \
|
||
/ \
|
||
2 + + 4
|
||
\ /
|
||
\ /
|
||
+
|
||
1
|
||
|
||
Although the positions of the points are different, point 1 is still the
|
||
top left of our texture.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ How to put it to screen
|
||
|
||
Okay, so now you have four points and know which one of them is also the top
|
||
left of our texture. What next?
|
||
|
||
If you think back to our tutorial on polygons, you will remember we draw it
|
||
scanline by scanline. We do texture mapping the same way.
|
||
|
||
Lets look at that picture again :
|
||
|
||
1
|
||
+
|
||
a / \ b
|
||
/ \
|
||
4 + + 2
|
||
\ /
|
||
\ /
|
||
+
|
||
3
|
||
|
||
We know that point 1 is at [0,0] in our texture. Point 2 is at [127,0],
|
||
Point 3 is at [127,127], and Point 4 is at [0,127].
|
||
|
||
The clever bit, and the entire key to texture mapping, is making the
|
||
logical leap that precisely half way between Point 1 and Point 2 (b), we are at
|
||
[64,0] in our texture. (a) is in the same manner at [0,64].
|
||
|
||
That's it. All we need to know per y scanline is :
|
||
The starting position on the x axis of the polgon line
|
||
The position on the x in the texture map referenced by that point
|
||
The position on the y in the texture map referenced by that point
|
||
|
||
The ending position on the x axis of the polgon line
|
||
The position on the x in the texture map referenced by that point
|
||
The position on the y in the texture map referenced by that point
|
||
|
||
Let me give you an example. Let's sat that (a) and (b) from the above
|
||
picture are on the same y scanline. We know that the x of that scanline is
|
||
(say) 100 pixels at the start and 200 pixels at the end, making it's width
|
||
100 pixels.
|
||
|
||
We know that on the left hand side, the texture is at [0,64], and at the
|
||
right hand side, the texture is at [64,0]. In 100 pixels we have to
|
||
traverse our texture from [0,64] to [64,0].
|
||
|
||
Assume at the start we have figured out the starting and ending points in
|
||
the texture
|
||
textureX = 0;
|
||
textureY = 64;
|
||
textureEndX = 64;
|
||
textureEndY = 0;
|
||
|
||
dx := (TextureEndX-TextureX)/(maxx-minx);
|
||
dy := (TextureEndY-TextureY)/(maxx-minx);
|
||
for loop1 := minx to maxx do BEGIN
|
||
PutPixel (loop1, ypos, texture [textureX, textureY], VGA);
|
||
textureX = textureX + dx;
|
||
textureY = textureY + dy;
|
||
END;
|
||
|
||
|
||
Do the above for all the scanlines, and you have a texture mapped polygon!
|
||
It's that simple.
|
||
|
||
We find our beginning and ending positions in the usual fasion. We know
|
||
that Point 1 is [0,0]. We know that Point 2 is [127,0]. We know the number
|
||
of scanlines on the y axis between Point 1 and Point 2.
|
||
|
||
textureDX = 127/abs (point2.y - point1.y)
|
||
|
||
We run though all the y scanlines, starting from [0,0] and adding the above
|
||
formula to the X every time. When we hit the last scanline, we will be at
|
||
point [127,0] in the texure.
|
||
|
||
Repeat for all four sides, and you have the six needed variables per
|
||
scanline.
|
||
|
||
|
||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||
þ In closing
|
||
|
||
As you can see, texture mapping (this type at least) is quite easy, and
|
||
produces quite a good result. You will however notice a bit of distortion
|
||
if you bring the polygon too close. This can be fixed by a) Subdividing the
|
||
polygon, so the one is made up of four or more smaller polygons. Much
|
||
bigger, but works; b) Using more accurate fixed point; or c) Figuring out
|
||
perspective correct texture mapping, mapping along constant-z lines etc.
|
||
|
||
When people write me, they often refer to my "tutes". This stems back to
|
||
Mark Feldman calling them such in the PCGPE. I always though a "tute" was
|
||
something you did with your car to gain someones attention. I dunno, maybe
|
||
its an Australian thing ;-)
|
||
|
||
I have been coding almost exclusively in C/C++ for the past year or so.
|
||
Sorry guys, thats all they will pay me for ;) Anyway, the trainers will
|
||
continue to be in Pascal for ease of understanding by beginners, but if
|
||
someone (*ahem* Snowman) doesn't start converting them to C soon, I will do
|
||
it myself. He also corrected any mistakes I made while he was converting,
|
||
so I'd prefer he did it (sort of a proofreader after release...)
|
||
|
||
Send me presents! It's my birthday!
|
||
|
||
Byeeeee.....
|
||
- Denthor
|
||
16-04-96
|
||
|