'=========================================================================== ' Subject: CATHEDRAL SCREEN-TEASER Date: 01-15-98 (23:30) ' Author: David A. Wicker Code: QB, QBasic, PDS ' Origin: pyramax@fastlane.net Packet: EGAVGA.ABC '=========================================================================== DEFINT A-Z '$DYNAMIC ' Cathedral Stained-Glass Window Screen-Teaser >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ' Written by David A. Wicker ' pyramax@fastlane.net ' http://www.fastlane.net/~pyramax ' --------------------------------------------------------------------------- ' As always, if you borrow anything from any source code for your ' shareware projects, please give credit to the original author! ' --------------------------------------------------------------------------- ' DEFINT A-Z and '$DYNAMIC as the first two lines of every QBasic program ' ensure maximum speed and maximum memory capability. ' They are chiseled in every single program I write. DECLARE SUB Center (A, A$) DECLARE SUB TR (T$) ' QBasic is a curious creature. It will insert these declarations ' automatically. If you are not using the percent keystroke % anywhere ' in your source code, use: ' ALT-S C % ALT-C to erase all occurances of % in your source code, ' then use shift arrow keystrokes to highlight the DEFINT A-Z and ' '$DYNAMIC to scoot it up to the top with Cut and Paste. Do you use the ' mouse ? I never do. Use SHIFT-DEL and SHIFT-INS to both cut and paste. DEF FNC$ (A$, A) = MID$(A$, A, 1) ' QBasic never came with a really big set of commands for string handling, ' so I developed most of my own with the easy-to-use DEFine FuNction command. ' In this case, it plucks out a single character from A$ at position A. ' Saves me keystrokes, yep, I'm lazy at times. :) A$(0) = "Cathedral v0.3 ù (C) 1998+ David A. Wicker" ' You can insert special keystrokes like that raised dot above there. ' Hold down the ALT key and without releasing it, tap ONLY on the ' numbered keypad, 2 5 4 . You will create a little square. ' Refer to your ASCII character codes available in QBasic help for a full ' listing. This can be dangerous for source code if misused, CTRL-P and ' any keystroke will insert that keystroke direct in your sourcecode, ' anything from backspace to hidden characters. Always save your ' sourcecode in ASCII. QBasic 4.5 does have a nasty habit of inserting ' something indigestible in your sourcecode through too many INP or OUTs ' and you will lose your source code if it is saved in the fast LOAD/SAVE ' format. It also makes printing it out later impossible. ' ' Saving in ASCII ensures that for whatever reason, if your sourcecode ' cannot be read in QBasic, you can bring it up under a text editor and ' manually take out the part that is causing it trouble. A$(1) = "You like ? Please send a postcard to let me know !" A$(2) = "3436 Clayton Road East ù Fort Worth, Texas ù 76116" ' Please! A postcard would be nice, or even an Email message letting me know you ' learned a little something from this source. :) FOR I = 0 TO 2 FOR J = 1 TO LEN(A$(I)) A = A + ASC(FNC$(A$(I), J)) NEXT NEXT WHILE A <> 11954: WEND ' I originally used this as a checksum to ensure no-one tampered with my ' .EXE when I released it years ago. I'm still pretty paranoid but not at ' the level I used to be. :) Splice = 9 ' Change this value to get some interesting effects: ' I.E.: 1, 2, 9, or 100 RANDOMIZE TIMER ' Any calls to RND or RND(1) will always have the same "random" values ' everytime you run your code unless you include this. You can "seed" random ' values too. Can anyone think of how to make a good encryptor with this? ' I used to protect files this way with the seed # being long integer. DEF FNR (A) = INT(RND * A) ' Use DEFine FuNctions like this one to create your own shortcuts to ' computations! For all the years I've used this, since all my variables are ' defined as integers from the DEFINT A-Z, I have always insisted on using: ' INT(RND*A) instead of: ' RND*A ' The results are the same, but it doesn't feel right in my head. :) Again: SCREEN 9 ' Resolution 640x350x16, the pixels are really flat and nice looking. ' Does =ANYBODY= use screen 2 today ? Eyyech! LINE (0, 0)-(639, 349), 0, BF K$ = "" X& = FNR(640) * 100& Y& = FNR(350) * 100& ' Math time! If you are =EVER= going to use a long integer that you know ' will get bigger than 32767, you have probably hit the dreaded: ' OVERFLOW error. Just like Pascal programming, you need to ensure all the ' variables inside know what type they are. I.E.: ' A=32767 ' B&=A+1000 ' OVERFLOW will rear its ugly head in this case. Convert it to: ' B&=A+1000& ' And then it will work fine. ' If there are no constant numbers, make the last item in the entry ' +0& for long integer, +0# for real, etc. ' You could go to the top and say: DEFLNG A-Z or DEFSNG A-Z, (which is ' actually the default, but then your program speed will be cut in half or ' worse. Stick with 16 bit integer. It's worth it in the long run. ' Using FNR we've just gotten random values! ' What other FuNctions can you think of making with this ? N = 1000 Z = 0 TT! = TIMER ' Timer is a REAL variable, you can check for it up to 100ths of a second ' If you put DEFINT A-Z in front of all your source codes, ' they will run considerably faster, and if you need non small integer ' numbers, use ! for Real, & for Long Integer, and $ for strings, ' but you knew that. :) DO K$ = UCASE$(INKEY$) ' Use UCASE$ to turn any string of any kind all uppercase, you should ' =NEVER= have to use OUT and POKE to force someone's CAP-LOCK or NUM-LOCK ' on. It's not only rude, it can get stuck backwards with it being lit and ' it acts like it's off. IF K$ = "E" OR TIMER - TT! > 30 OR TIMER < TT! THEN GOTO Again ' After 30 seconds, or if "E" is pressed, clear the screen and start a new ' picture. Lowercase "e" acceptable too, via our UCASE$ from above. IF Z MOD 10 = 0 THEN WHILE TIMER - TT2! < .01: WEND: TT2! = TIMER ' Every 10 cycles, a hundredth of a second will pause IF K$ = "P" THEN NotActive = 1 - NotActive: K$ = "" ' Pause if we really want to Z = Z + 1 IF Z = 32767 THEN Z = 0 IF Z MOD N > N \ 2 THEN C = (C + 1) MOD 16 COLOR C IF NotActive = 0 THEN X = X& \ 100 Y = Y& \ 100 ' the forward / is to receive decimal divison, the backward slash is for ' integer division, it is considerably faster and since we know our results ' will be integer, we use the backslash every time. PSET (X, Y) PSET (640 - X, Y) PSET (X, 350 - Y) PSET (640 - X, 350 - Y) END IF X& = (63900 + FNR(1000) - X&) - ABS(Y& - 100) / Splice * 3 Y& = (34900 + FNR(1000) - Y&) - ABS(X& - 100) / Splice ' Swing our pixels around like a tornado in a paintbucket! ' Notice these values are *100. Integer math will always be faster than ' floating point math. They have the accuracy of up to two decimal places ' because I divide by 100 when I plot them. ' If they were only 639 and 349, the stained-glass window would not look as ' pretty. IF X& < 0 THEN X& = X& + 64000 IF Y& < 0 THEN Y& = Y& + 48000 IF X& > 63900 THEN X& = X& - 64000 IF Y& > 34900 THEN Y& = Y& - 35000 ' Flip our plotter to opposite end of screen if it goes too far. ' Always try to monkey-proof your software. Just because you are asking ' someone who runs your software for a particular input, file, or event, ' doesn't necessarily mean they will follow the rules. I never do. :) LOOP UNTIL K$ > "" SCREEN 0, 1, 0, 0 WIDTH 80 COLOR 7, 0 CLS PRINT STRING$(80, " "); ' Some strange versions of Win95 put a blue bar at the top of a text screen ' when you leave graphics. Mine doesn't, but yours may. I only included it ' here because I originally wrote this on a Win95 platform computer that ' had it. It is also the platform I lost the source code to my ' Internet Backdrop generator. I still have the .EXE but the source is gone. ' My boss wiped it accidentally. :/ LOCATE 10 ' Many commands can use abbreviated arguments in QBasic. ' LOCATE 10 will put the cursor at the VERTICAL 10th position. ' LOCATE,10 will put the cursor at the HORIZONTAL 10th position. ' In both cases, for vertical, the horizontal is unaffected, and vice-versa. ' This abbreviation also applies to the SCREEN command. Tap F1 on the ' word SCREEN to see available options. Why do I use QBasic above all other ' languages ? It's built-in help is the best I've seen, period. ' Also I'm a stick-in-the-mud for running my program every 5 minutes to see ' what little changes I've done affected it. :) ' Tap CTRL-F1 to bring up the last help you were looking at. Center 1, A$(0) Center 5, A$(1) Center 4, A$(2) ' Example of calling a SUBPROGRAM, parentheses and CALL are not needed for ' the arguments. Naturally, if you are calling a single SUBPROGRAM with ' no arguments and you use the ":" to separate it from another command on the ' same line, QBasic will get confused and think it is a marker label for ' GOTO and GOSUB. Try to avoid the ":" as much as possible. It's a bad ' habit. ' Save your keystrokes. :) COLOR 7 LOCATE 23 TT! = TIMER: WHILE TIMER - TT! < 1 AND TIMER >= TT!: WEND ' I learned about using TIMER to delay or pause execution from the WormHole ' QB demo. I gave credit for them in Treasure Hunter in the credits listing. ' :) ' Always use TIMER for loops, and yes, you can pause for tenths of a second ' too. if you use FOR I= to / NEXT loops, just because your computer runs ' at a good speed by "fudging" the numbers, there is no way it can run the ' exact same speed on anyone else's computer. ' I am forever inserting the TIMER routine into some of the very good games ' that have been received into William Yu's ABC packets by others in QBasic ' but the programmer did not foresee a pentium attempting to run them. ' By the time I blink the game is over. :) DO: LOOP UNTIL INKEY$ = "" DO: LOOP UNTIL INKEY$ > "" ' There is no way that a keystroke can be less than nothing, so you do not ' need <>, save yourself a keystroke, I always do. :) ' Tap F2 at this point to see the subprograms. If you've never used ' Subprograms before, you really should learn them! They make managing code ' a lot easier and are much more powerful than GOSUB or GOTO. REM $STATIC SUB Center (A, A$) : SHARED ColFlip ' using SHARED inside a SUB makes it global to your entire program and it ' will not get erased once you exit the subprogram, all variables are ' initialized to zero (0) when you first run a program, so I use that as a ' starting point for my variable flags before they are set to another value. LOCATE , 40 - LEN(A$) \ 2 ColFlip = A TR A$ PRINT PRINT END SUB SUB RGB (N, R, G, B) ' Original Author: Unknown! I "earned" learning this over the internet ' chatting with someone. I traded it for the source code to a QBasic fill ' any graphic region routine that used PSET only. If there is a need for ' this today, I'll release that source too. Huzzah! =NEVER= use PALETTE! ' Although PALETTE may run fine and well on your computer, on others, it ' takes better than 4 seconds to only change 256 colors! ' Pentium computer notwithstanding! OUT &H3C8, N OUT &H3C9, R OUT &H3C9, G OUT &H3C9, B END SUB SUB TR (T$) : SHARED ColFlip ' TR to me means TRANSMIT. It is a carry-over when I wrote BBSs years ago. ' Ever consider writing your own fancy PRINT routines ? As long as they are ' strings, you can make your own this exact same way! Be creative and set it ' so special unusual characters like @ or ^ do curious things to the string ' being sent through, not just for color, but for typeface, appearance, ' location, speed of display, audio, etc. ' Back on the Apple ][+ when I wrote Orbs of Ankhar, I used CTRL-E for a ' click sound, CTRL-F for a fighting sound (clash), and CTRL-G for a quick ' warble up. Richard Garriot used a CTRL-G TSR when he wrote Ultima I years ' ago on the Apple ][+, and yes, I had a chance to talk to him over the phone ' years ago when he was starting out. :) FOR I = 1 TO LEN(T$) C$ = FNC$(T$, I) ' Remember, this is our nifty little nick out a single character function ' defined in the beginning of the source. IF C$ = "`" THEN C$ = CHR$(34) ' This was not used in this program, but as you know, or should, you cannot ' insert a quote key inside a print statement. I.E.: ' Print"She said, "Hello There!" --> Will not work. ' You'll get back. ' She said, 0 0 ' So, since we're using a fancy text-displayer, whenever it sees the seldom ' used "`" key, it converts it to print out CHR$(34). ' DATA statements balk at using the comma "," as part of a string unless you ' have an opening quote first: ' DATA "Bread,Milk,Eggs","Cedar,Redwood,Birch" IF C$ < "A" OR I = 1 THEN COLOR ColFlip + 8 ' Another example of an abbreviated argument: ' COLOR,5 would change only the background to 5 leaving the foreground ' untouched. PRINT C$; IF C$ <> " " THEN COLOR ColFlip NEXT ' Before I close, I would like to emphasize the overuse of line numbers that ' are still apparent in today's QBasic source codes. People, they are not ' needed! It is far easier to write code like this than to break it all down ' to line #'s. Force yourself to learn it because GWBASIC is as old as the ' Pet Rock and just as useful. :) Usage of the colon ":" in codes to pack ' more than one statement to a line should really be a big no no as well, ' especially if it forces the single line to span greater than 80 characters ' across so the source code has to be shifted all to the right to read it. ' Use IF THEN {insert the body of what occurs} and ENDIF on multiple lines, ' please. ' One Final Thing, if you turn off the TAB setting under (O)ptions, ' (D)isplay, you can hit spacebar twice to indent clean code and not have it ' jump 8 characters to the right. Better to have a small indentation than ' one that forces programming lines greater than 80 characters across. ' ' Also, please EMail me if you know the POKE or OUT command to convert the ' FLASHING state in regular 80x25 text to be the high-bit color background, ' like the Quickbasic editor does when you select (O)ptions and (D)isplay. ' Notice how you can set the background to greater than color #7 and it ' displays it like it should. No-one I know uses the flash in text anymore, ' so I don't want to have the flash in my text-handling library. ' pyramax@fastlane.net END SUB