![]() |
|
Close Help |
PCOPY! Issue #40 ~ March 15th 2007 |
||||||||||||||||||||||
|
|
|||||||||||||||||||||
Regular Columns: From Our Editing Desk (MystikShadows) Submitting to PCOPY! (MystikShadows) Letters To The Editors (Mixed Contributors) Quote Of The Month (E.K. Virtanen) In The News (Mixed Contributors) Exit Issue (MystikShadows) Special Corners: The Useless Corner (Hartnell) Contest : The Dumbest Game (Hartnell) Reviews And Presentations: Introducing Yabasic (MystikShadows) Introductory Article On XBLite (Guy (gl) Lonné) About thinBasic (Eros Olmi) Epic Crusade (Jare) Articles: A piece of history: Star Trek Game (E.K.Virtanen) The Evolution Of BASIC (MystikShadows) Tutorials: Programming Simulation Games (MystikShadows) Basic4GL Tutorial: Tile Maps (Linkage) Introduction to the FreeBasic Extended Types (Rick D. Clark) Simulating Polymorphic Methods... (Rick D. Clark) FreeBASIC File/Folder Management (MystikShadows) |
MystikShadows E.K. Virtanen Hartnell Richard D. Clark Guy (gl) Lonné Eros Olmi Linkage Jare |
|||||||||||||||||||||
~ REGULAR COLUMNS ~ |
||||||||||||||||||||||
From the Editors: by Stephane Richard (MystikShadows) |
||||||||||||||||||||||
Welcome to this 4th edition of PCOPY! As you might have noticed we're giving PCOPY! a new look. There's been alot of comments about how PCOPY! looked, How difficult the colors were on the eyes. So here is our attempt at making PCOPY! easier to read while remaining true to the PCOPY! tradition of monospaced characters. On a personal note, I'd like to share with you that PCOPY! is broadening its horizon so to speak. Indeed users and creators of other basics are starting to notice PCOPY! which means that we are right on track with one of PCOPY!'s main goal which is to be a magazine for all basics. We'd like to thank all contributors of articles for any basic. we can't wait to get even more contributions about even more BASIC dialects. We have yet another great line up of material for your reading pleasure. There is always something going on in the BASIC communities and as always we did our best to bring you the most current and up to date news on what's happening. We have our regular columns of course and your reviews and presentations section (which we now isolated as we plan to write a whole lot more presentations to help you learn more about what BASIC is out there). So get yourself your favorite drink, sit back and enjoy the contents we've put together for you
at your own pace. |
||||||||||||||||||||||
Submitting to PCOPY!: by Stephane Richard (MystikShadows) |
||||||||||||||||||||||
As you probably noticed, we have a list of contributors. Everyone that submits something gets his/her name added to this list for the particular issue the submission appears in. We can't claim to know every single BASIC dialect out there nor can we claim to know how to program in all of them. There are just too many of them. Hence, this is an official invitation to those of you that do know a specific BASIC dialect well enough to write about it. Help us make PCOPY! the most complete BASIC magazine there can possibly be by sending us submissions about them. When we say submissions we mean anything that pertains to the specific BASIC dialect in question. Submissions can range from simple news item (a new version comes up, a new library is available and the likes), they can be personal reviews of a given BASIC interpreter/compiler, they can be tutorials, tips and tricks that shows readers how to accomplish a given task in the BASIC of your choice. The choice is yours. Submissions will help make PCOPY! even better than it is and the end result of that is that readers will have better BASIC related material to read in every issue that comes up. So don't be shy, you know something others don't about a given BASIC, let us know about it, send us your submissions and we'll take it from there. If you're not sure how good a writer you are don't worry, if needed, we'll edit and format the submission accordingly. So please, submit whatever you have time to write. All submissions can be sent to my email and will typically be added in the issue that is currently being worked on at the time the submission is sent to us. ![]() |
||||||||||||||||||||||
Letters To The Editors: By Mixed Contribytors |
||||||||||||||||||||||
Letter from Gandalf ParkerI love the PCopy magazine. Thanks for posting about in on the YaBasic forum. But Im wondering, I dont see any mention of YaBasic. Im an old guy. I got into basic back when you had to. It was what your PC ran on. I got back into it because my linux server loaded yabasic. The only other basic it had was BW Basic. I stuck with YaBasic because it had a Windows version when meant I could use the same quickie little programs on my desktop and my server. Now I use YaBasic for web CGIs, admin scripts, fancier batch files on my windows machine, just about anything where I need something working really quick. Its still in the debian catalog for any admin to easily load and use, so Im thinking it maybe should be mentioned.
|
||||||||||||||||||||||
Quote Of The Month: By E.K. Virtanen |
||||||||||||||||||||||
Quote of the Monthsid6.7, Z!re, E.K.Virtanen & {nathan}E.K.Virtanen thanks Z!re for giving good laughs. ;DBackground of quote: in here and in here.
changed to: |
||||||||||||||||||||||
In The News: (Mixed Contributors) |
||||||||||||||||||||||
FreeBASIC - Classic Art Slider Puzzle Game By Lachie Dazdarian FreeBASIC - BLOC8 Created By BeBeliOuS FreeBASIC - Owen announces his FB CAD program created in FreeBASIC FreeBASIC - subxero has an excellent GUI project. FreeBASIC - AFLIB2 Remixed created by Adigun A. Polack. xbLite - Vixen 0.94p released. BCX - Currently at version 5.11. Decimal BASIC - Now at version 5.9.7. HotBasic 5.2a (14'th Mar. 2007) now integrates HotOptimize pre-processing merely by use of the -O switch (optimize), causing automatic call to hotoptim.exe followed by compile of the optimized code. The only requirement is hotoptim.exe (HotOptimize download) in your HotBasic directory. KBasic Software Atelier (V1.6) is planned to be released on 30 March, 2007. V1.7 is expected in May 2007. 16'th Feb. 2007: Play Basic V1.65 DX7 ALPHA (Retail Compiler Only Beta) - (Available for Registered Users ONLY) Some updates made at BBC BASIC website. GW-BASIC forum was not dead as i told in last issue. It came back in the books of living ones right after last issue was released. QBasic on Linux Club still swear in name of QBASIC. QB is an old warhorse and personally i love linux, so nice to see groups like this. QBasic Gui Wiki. is still kicking. QB'rs, head yourself there. CoolBASIC is not so dead than it was supposed to be. There is a group of peoples who are interested to invastigate possibilities to create an CoolBASIC compiler for linux platform. At same time, project to translate CB documents from Finnish to English has boosted a bit. New translated documents pop's out time to time. Brutus2D V1.7 released March 7, 2007. |
||||||||||||||||||||||
|
||||||||||||||||||||||
The Useless Corner: by Hartnell |
||||||||||||||||||||||
Some things about Commodore BASIC and the C64 I find completely useless. Maybe its because time has erased my memory of what to do with these things. In The Useless Corner, I will challenge you to give me a practical purpose for a feature I think is Useless. This issue's useless thing is LIST. It's true, LIST is very useful. But, look at this completely useless use of LIST : 10 PRINT "THIS PROGRAM LISTS ITSELF" 20 LIST The output of this program is : THIS PROGRAM LISTS ITSELF 10 PRINT "THIS PROGRAM LISTS ITSELF" 20 LIST Here's my challenge to you. Find a practical purpose for being able to LIST the code of the program that's running. You can send it to : shawn.Hartnell@gmail.com |
||||||||||||||||||||||
Contest : The Dumbest Game by Hartnell |
||||||||||||||||||||||
Every month we will be running a contest. This month's theme is the DUMBEST GAME EVER. Here are the rules:
Even though PULL MY FINGER is just an example to get you started, it shows you how dumb a BASIC game can be. If the entries are as dumb as this, you have some stiff competition. Hit Some Guy 10 REM HIT SOME GUY 20 PRINT CHR$(147) 30 PRINT "HIT SOME GUY WITH A STICK? (Y/N) 40 INPUT A$ 50 IF A$ <> "Y" GOTO 80 60 PRINT "THE GUY SAYS 'OUCH!'" 70 PRINT : GOTO 30 80 PRINT "COWARD" 90 END Pull My Finger 10 REM PULL MY FINGER 20 PRINT CHR$(147) 30 PRINT "PULL MY FINGER? (Y/N)" 40 INPUT A$ 50 FOR I = 1 TO 2000:NEXT I 60 PRINT "PPPFFFFT." 70 END Good luck. You'll need it. |
||||||||||||||||||||||
|
||||||||||||||||||||||
Introducing Yabasic: by Stephane Richard (MystikShadows) |
||||||||||||||||||||||
INTRODUCTION:In today's world, it gets harder for new BASIC dialects to make their mark in the big pool of BASIC languages that exists today. I was introduced to Yabasic a few days ago by a reader that wondered why it wasn't covered in PCOPY! in any way. So I went to the website, downloaded a copy of the latest implementation of Yabasic and gave it a good try. As a result, I just had to present it to our readers. Yabasic is what I like to call a good old BASIC. Here is a screenshot of yabasic executing the demonstration program provided in the installation:
This means that Yabasic is ready to run something. You can type commands in the environment or pass a file as a commaand line to yabasic.exe and it will execute the file (much like when using QBasic. Note that you can use an editor to edit source files as yabasic does not save them from within the environment. In Windows, the installation associates the .yab extension to yabasic.exe so that when you double click on the source file you created it will be executed automatically. ABOUT YABASIC'S SYNTAX AND GRAMMAR:Yabasic's syntax is very crisp and clear. It's a bit different than other BASICs but in my opinion it actually helps Yabasic set itself apart as well as remain a clear and fun to use syntax. Here's a small sample code to give you an idea: clear screen for a=1 to 200 print color("red") "Hello !"; print color("blue") "World !"; next a r$=getscreen$(0,0,20,20) for x=0 to 60 putscreen r$,x,0 sleep 0.1 next x As you can see it definitaly looks and feels like basic. And as you might have noticed it has some nifty commands to get and restore the screen (or even parts of it). It can do some pretty cool things even just with the print command which combines color, screen location and contents to be printed into one command with everything optional so you don't have to enter empty parameters if you're not using part of the syntax. Yabasic isn't limited to that either, it does graphics, it does them quite elegantly I might add. With statements like circle, rectangle, box and others which give it a complete set of graphic commands it's able to easily create some great graphics and graphic effects. It has a good set of string manipulation functions as well to allow to process strings it efficient and useful ways. Add to that some file manipulation statements and other useful construct like repeat loops and others and you have yourself a great BASIC dialect to have fun with. Here's another sample code that uses graphics commands: open window 200,200 new curve line to 100,50 line to 150,150 line to 50,150 close curve New Curve essentially starts a series of lines (where each instructions starts from the end of the previous instruction allowing to draw lines that follow each other to form a shape. When you're done drawing your shape you simply issue a close curve to stop the process. I think this is one of the most intelligent ways of implementing this type of feature. OTHER FUN YABASIC FEATURES AND FACTS:One of the thing you can read on the website is that although Yabasic behances like an interpreter it is actually an interactive compiler. Indeed when it gets code from a file passed as a command line parameter or code you type in the environment. That code gets compiled before it gets executed. It uses a principle of a simple stack machine and the code is ready to execute. So essentially though it works like an interpreter it is actually rather fast in it's execution. Yabasic was created using Flex Bison as it's main engine. So it's grammar is defined in BNF (Backus Naur Form) Which then creates 2 C programs which used together produces the yabasic program. Flex and Bison is a great way to create a grammar (and allow to validate it as well) so I think that using it in this project is a great decision in itself. You'll be happy to learn that Yabasic is released as Open Source under the GPL licensing scheme. Hence it's free, you can download it all you want explore the source code, learn from it or do whatever you want that GPL allows (which is quite a lot).
WHERE TO FIND OUT MORE ABOUT YABASIC:If you are as curious about Yabasic as I was when I learned about it. pay a visit to The Yabasic Website. From there you can take a look at the history of the creation of the project, the FAQ, you can download and try Yabasic for yourself and see for yourself how great a dialect of basic it is. I also invite you to consult the yabasic manual where everything is pretty straightforwardly documented and easy to read. You'll see how rich the Yabasic syntax is and how everything works to make Yabasic do what you want it to do. IN CONCLUSION:BASICally speaking, Yabasic is one of the better implemetations of the BASIC language I've seen. I'm glad I was introduced to it and would like to thank Gandalf for letting me know about it. If there's one thing I can say against Yabasic is simply that since it's so close to a compiler (flex and bison based code) a compiler that produces executables int he classic sense of the word might not be that hard to do and I believe would open alot of doors for Yabasic in my opinion. Other than that, Yabasic is a great BASIC to use. This article is of course based on my own personal
experience using Yabasic. The best thing I can tell you is to grab a
copy of it and try it for
yourself. Be your own judge and see for yourself what
Yabasic is all about. Yabasic is a great idea that can be turned into an
even better implementation of that
idea. Don't take my word for it. Have a look and see for
yourself. Until next time, happy coding. |
||||||||||||||||||||||
Introductory Article On XBLite: by Guy "gl" Lonné |
||||||||||||||||||||||
IntroductionStephane "MystikShadows", editor of PCOPY!, asked David Szafranski for a short presentation of XBLite to publish in the 3rd issue of his BASIC e-magazine "PCopy". Follow here the article, which I authored on behalf of David. In this personal article, I will try to convey the sheer pleasure that I have to develop in XBLite. I. My encounter with XBLiteDear Reader, you might want to skip my personal history and go directly to "II. What Can XBLite Do?" since the article is about XBLite, not my love affairs with languages. I am a professional programmer since 1980. The first application I wrote (an accounting package) was on a Perkin-Elmer, using an interpreted Basic enhanced with some assembly routines. The following year, I met Her, COBOL, on a Triumph-Adler (with a Texas Instrument processor). O my Lady, after a quarter of a century long a relationship, you are still the love of my (programming) life! But, life is life! I met this sexy Blonde in 1989: C. Boy! What a hot relationship! But no children. Coming from a COBOL background, I could not produce any program after a whole year trying hard. I looked for professional council and I attended a 1-year course at the New York University School of Continuing Education. I was lucky enough to have an outstanding teacher, who taught me all the tricks of the C trade. In 1991, I purchased from Tandy the DeskMate SDK and from Microsoft, MS C version 5. Unfortunately, (not for Bill G.) Windows™ outplayed all competition on Intel processors; so bye-bye DeskMate SDK and my investment in it! Then, Visual Basic crossed my path in 1999: pretty face and beautiful forms. I discovered a whole new world and I was back to the Basics! Getting tired of being so shielded from Windows™, I decided to explore the WIN32 API realm. I was thinking to go back to my old mistress, Miss C. But I discovered XBLite in 2005. And it was love at first sight: it was my Miss C, but with strings! Yes, C is so great at everything but handling strings, and here is XBLite, almost as good as C at everything, with her additional built-in string support! (The C-string model, by the way). OK, Dear Reader, let's talk business, XBLite programming business! II. What Is XBLite?XBLite is a BASIC compiler, mainly for Windows™ GUI developments. Its syntax is clearer and easier to get to grips with than C, with almost matching performances (coined by phpbb's Michael, thanks M.!). XBLite is free, open-source, and published under GPL and LGPL. Its workbench comes with the compiler, XSed, utilities, demos, source code and reference manual. XSed is a scintilla based programmer editor, meaning it has built-in syntax colorization, folding capability and is optimized to edit XBLite programs. The entire workbench can be downloaded from David Szafranski's site. The compiler creates Win32 programs (GUI or console). Free add-on DLLs are available at David Szafranski's site, e.g. DLLs for sending email via SMTP, to embed a web-browser from within a program, to load and save JPG, GIF, BMP, DIB, RLE, TGA, PCX image files, to create card games, etc. XBLite has a GUI designer: Vixen, © GPL 2006 by the Vixen Team: John "prujohn" Evans, Guy "gl" Lonne, Rhett "lzdude69" Thompson. Vixen is still underway by this article's Author. A downloadable version is posted regularly in the XBLite Google Group. Follows an excerpt from David Szafranski's site. (----------------------- Beginning of excerpt -----------------------) III. What Can XBLite Do?XBLite is as well suited to novices as programming wizards, and is appropriate for virtually all programming tasks. For science and engineering, XBLite has extensive math libraries, including complex number arithmetic. For business, XBLite has a 64-bit integer data type, user-defined types optimized for database I/O. XBLite can also connect to ODBC databases or use database libraries such as SQLite. For game developers, XBLite can call OpenGL, SDL, or DirectDraw libraries. For all applications, XBLite designed to support rapid development of compact, efficient, reliable, readable, and well structured programs. And now, XBLite includes a very powerful colored syntax code editor, XSED, which allows the programmer to create and compile programs with ease. IV. Why XBLite for Windows™?XBLite is a "younger brother" of XBasic. XBasic was developed by Max Reason to be used under MS-Windows™ and LINUX OS's. In 2000, he made the entire language, compiler, and PDE freely available under an Open Source GPL. The XBasic language itself has not been altered so console programs in XBasic will run identically under XBLite. The XBLite compiler is also released under the same Open Source GPL license. But XBLite has been enhanced for use under Windows™. It is now possible to:
And, all of the Windows™ common controls and common dialogs are now available to create win32 native graphical user interfaces (GUIs). (----------------------- End of excerpt -----------------------) If David's website is the reference for xblite, it is because David is the one responsible for xblite. Without David, xblite would not exist. He was the one that stripped XBasic to the bare bones and collected all Windows code of it and made it work without a 1.5MB runtime DLL. Only he can tell you how much time and effort it took to transform an idea to a working compiler. Also xblite compiler benefited from the work of Greg aka "Bushpilot". Without his outstanding work, xblite would still use spasm as an assembler instead of the actual goasm. (Thank you efgee for pointing me this out). The size of the runtime DLL, xb.dll has been reduced to 175kb from 1523kb. With a PE packer such as UPX, the XBLite runtime DLL can be reduced to around 50kb. This huge size reduction was accomplished by taking out the individual libraries in the runtime, Xui, Xgr, Xst, Xma, Xcm, Xin, etc., and making them external DLL libraries (except for the critical parts of Xst). V. How I do use XBLite?I always evaluate the size of a project before I start to get organized for my developments. My projects come in 4 sizes:
As you will see, XBLite can address projects of all sizes, using the appropriate techniques though. I. The small XBLite projectXBLite is extremely productive for S projects: like writing quick and dirty tools for the Windows™ environment. For example, having to fill an Excel sheet of amounts in dollars, when the original sheet was expressed in euros, I wrote in about an hour (I was still learning) a small XBLite program that accepted an amount in euro, computed the equivalent amount in dollars and placed the result into the Windows™ clipboard, ready for a Ctrl+V into the proper Excel cell. An advice: get familiar with XBLite standard library (here, for the clipboard-related functions). Bruce M. A. asked: Why code the Euro to Dollars conversion in XBLite, when you could have used VBA and defined a function =ConvertToDollars()? Because my rule book reads:
("You see, Bruce M. A., reasonably done, if not for the good reasons!") XBLite shines over C because of the time saved not to declare the variables, and because the C function library is readily available (with an IMPORT "msvcrt"). An S project will remain less than a thousand lines, comments included. Comments are sparse, the code speaking for itself. A small project can serve as a prototype of a medium project, to experiment new techniques for instance. Using XSed as a programmer editor (as opposed to ConText for instance), all code can be typed in lower case since, if the auto-uppercase feature is active, all XBLite keywords are recognized and automatically changed in upper case. Some technical characteristics:
2. The medium XBLite projectAn M project is a successful S project, with a code facelift. I design for reuse: hopefully, some functions will end up in a library (DLL), so I craft them carefully. Otherwise, it has the same technical characteristics as the S project. It will remain less than 5000 lines, comments included. The functions are well commented (that's the facelift). Keep in mind that an M project can also evolve into an L project when its size outgrows the 5000 lines. I use solely XSed as the programming editor and start an editing session with Alt+F8 to fold all functions. I also use Ctrl+Shift+B to "Show Function Browser". 3. The large XBLite projectIts size will grow up to tens of thousand lines. All functions are candidate to end up in a library (DLL), to keep the size manageable. Comments are proficient and are addressed to the XBLite community, because I will publish some general-purpose libraries at the XBLite Google group. Some technical characteristics:
4. The extra-large XBLite projectIt is a team project, hopefully with an experienced project leader. Some technical characteristics:
I would label XL projects those using:
Hopefully, as a collective effort, XBLite will reach the maturity of C in this area, including at pre-processing time, with the help of the M4 pre-processor. VI. About code re-useDavid Szafranski wrote: Today, there is a wide variety of libraries available on the net, both in DLL form and in source code form. XB is capable of calling C routines, so one could just use a package like GMP as a DLL, or download source code and re-write it; much simpler than starting from nothing. ConclusionWith XBLite, I am offering you an adventure: do your programming work under the Windows™ environment and join a generous community, pulled upward by David Szafranski, whose endless energy and kindness kept baby Windows™ XBasic alive and maturing. Related links:
XBLite contributions:
|
||||||||||||||||||||||
About thinBasic: by Eros Olmi |
||||||||||||||||||||||
IntroductionEasy to install, easy to master, professional help, full features scripting language. All numeric and string data types available, dynamic strings up to 2Gb automatically managed, user defined data types, functions and subs, dynamic functions calling using function name composed at runtime, modular structure with dynamic modules loading, extensible language with external user defined modules, SDK to develop new thinBasic functionalities using different compilers, more than 1000 keywords, more than 3500 predefined constants, more than 15 modules covering many programming aspects already developed, specific editor/ide full of options and tools, plain text or obfuscated scripts and more important coherent Basic syntax, high execution speed, updated and fixed faster than any other development environment ever seen, active support forum with nice people always open to help each other. All this and much more is thinBasic. A Little Bit About thinBasic GenesisthinBasic project started as a little automation script engine, originally named AutoProc. At that time, I was searching for a tool to be able to run processes, interact with them, send mail and do ftp. Very few programs were available. Of the ones I tried, they were lacking one or more of the functionalities I needed. So, I decided to start making my own tool. After some time it turned into an interpreted language. At first, I was alone in developing thinBasic. After 2 years a friend of mine, Roberto, joined the project. We share the same deep passion for computer programming and in particular programming to solve everyday real problems faced by company IT departments. Ok, now stop with the history and back to thinBasic. What Is thinBasic?thinBasic is a script language. It means thinBasic is able to get a text file as input and execute it on the fly. No compilation, no intermediate code, just a plain text file and go. Text file is analyzed and executed immediately. Those text files are called script files. Here is a screenshot of the environment windows. The ThinBasic Environment How To Create A Script FileThinBasic scripts can be created with any text editor able to create text only files. But thinBasic has its own editor/ide called thinAir. You can execute thinAir from the thinBasic menu under the windows applications menu. If you want to edit a thinBasic script file, just right click on it and choose edit from the menu. You will find that thinAir has a lot of unique features that will simplify thinBasic development. Here is another screenshot featuring some games developed in thinBasic. Some Game Screenshots How To Execute A Script FilethinBasic is integrated with the Windows shell. It means that you can execute a script simply by double clicking on it like a standard compiled application. thinBasic scripts can have the following file extensions:
Types Of ScriptsthinBasic can execute 2 type of scripts: plain text script files or obfuscated script files. Plain text scripts are standard text files you can create with thinAir (thinBasic editor) or other text only editors like any other standard program. Obfuscated scripts are plain text scripts transformed by thinAir (thinBasic editor) into crypted and compressed files. This version of script are useful when you need to distribute you application, but you do not want to share the source code, by choice, or because they contain sensible data like passwords or whatever you want to keep secret. To create an obfuscated script, open your plain text script file into thinAir. Use menu Tools/Obfuscate. thinAir will create a new file in the same directory of the original script file with the same name but with .tbasicx or .tbasiccx extension. Attention: always keep the original copy of the plain text script, because no one can decrypt an obfuscated script back into its original clean form. How to get helpthinBasic help is continuously being updated. We try to do our best to create professional and easy to be used help material. When installed, thinBasic has a .chm help file under the thinBasic\Help directory. We also produce some downloadable help files both in html and a .chm format. How to get supportthinBasic has its own support forum at: http://community.thinbasic.com/ Where to download thinBasic and some words on thinBasic versioningthinBasic can be downloaded from: http://www.thinbasic.com/index.php?name=CmodsDownload We use 2 lines o development: stable and preview. Preview line is the ongoing development. Every time we fix a bug or add new functionalities or make interesting changes, we release thinBasic as a preview version. In this way everyone can immediately test, try and use new functionalities without a long wait. We are very transparent on this. Preview updates are quite frequent, 1/2 every week. Some times even more than once a day. It all depends on bugs found and features added. thinBasic internal structurethinBasic has a modular structure. This means that all main language functionalities are all together in a single DLL. All other specific functionalities are separated into external dlls that we call modules. The main thinBasic module is called the Core module and corresponds with the thinCore.dll file. This module is in charge of all main scripting functionalities like: script loading, parsing and execution, memory handling, script flow, string and numeric handling, load/unload of other modules when needed, interfacing with external dlls, interfacing with Windows API. All other functionalities are handled by specific modules. For example: file and directory handling, Console, OpenGl, user interface, sounds, Ftp, SMTP, advanced math, crypto, Modules are loaded by the main Core engine only when needed by the script. For example, when you need a function developed into a specific module, for example functions working on files like File_Load or File_Save, you first need to tell thinBasic you want to use the File module. To do this, add the following line into your script: USES "FILE" This will tell thinBasic your script needs the File module. thinBasic Core engine will load the File module and will add to the current script execution all the functionalities of the FILE module in terms of functions and equates (constants). So, for example, if you need to use functions for Console, Files, Ftp and SMTP inside your script add the following 4 lines: USES "FILE" USES "Console" USES "FTP" USES "SMTP" Supported data types and variablesthinBasic is a typed language. All variables must be declared before using and every variable must have a type. thinBasic natively supports the following data types:
Single variables, arrays or matrix up to 3 dimensions can be declared using all the mentioned basic data types. Variables have global or local scope inside functions or subs. Functions/SubsthinBasic supports Functions and Subs (subroutines). Every Function or Sub can have up to 32 parameters. Parameters can be optional. Every parameter can be passed by reference or by value. Arrays and structures are always passed by reference. Execution flowThe following program flow structures are supported IF/THEN/ELSE/ELSEIF/END IF FOR/NEXT/ITERATE FOR/EXIT FOR WHILE/WEND/EXIT LOOP DO/LOOP with WHILE or UNTIL clause SELECT CASE/END SELECT KeywordsthinBasic has more than 1000 native keywords covering many different programming areas. Source Code ExamplesA few source code examples to give you an idea of thinBasics power and simplicity. Loading text csv filesHow many times have you needed to load a csv data file? Those files with a comma (or other char) delimited fields? How many For/Next loops did you use? uses "file" '---Tell thinBasic we need file module '---Specify the csv file to be loaded and parsed DIM FileToLoad AS STRING VALUE APP_SOURCEPATH & "CSV_SampleData.csv" DIM MyMatrix() AS STRING '---Will hold the data DIM nLines AS LONG '---Number of lines loaded DIM nCols AS LONG '---Number of colums loaded '---Just one line do the job of loading file data, '---parsing text lines, dimensioning and filling the matrix. PARSE(FILE_LOAD(FileToLoad), MyMatrix(), $CRLF , ",") '--Now get the number of lines and max number of columns parsed nLines = UBOUND(MyMatrix(1)) ---Elements in dimension 1 nCols = UBOUND(MyMatrix(2)) ---Elements in dimension 2 MSGBOX 0, "Loaded file: " & FileToLoad & " contains:" & $CRLF & _ nCols & " columns" & $CRLF & _ nLines & " lines" Function evaluation at runtimeAnd what about solving y = f(x) equations, taking equations from a string? Can you imagine how many lines of code is needed to perform this kind of operations in other languages? This is a thinBasic example: USES "CONSOLE" '---We need Console module to write output USES "EVAL" '---We need Eval module to evaluate math strings DIM t0, t1 AS DOUBLE = TIMER '---Some timing variable DIM MyFunction AS STRING '---Will contain math function to eval '---Define Y = f(X) ... function inside a string MyFunction = "y = COS(x) * 10 + SIN(x)" '---Tells eval engine to define new 2 variables: x and y Eval_SetNumber("x", 0) Eval_SetNumber("y", 0) '---Define a looper and its max DIM Count AS LONG DIM MaxCount AS LONG VALUE 50 FOR Count = -MaxCount to MaxCount '---Set X value Eval_SetNumber("x", Count) '---Eval MyFunction Eval(MyFunction) '---Write some info output CONSOLE_WRITELINE(format$(Count, "0000") & " " & Eval_GetNumber("y")) NEXT '---Measure the ending time t1 = TIMER '---Final results CONSOLE_WRITELINE("------------------------------------------------------") CONSOLE_WRITELINE("Time in seconds for " & str$(MaxCount * 2) & " loops: ") CONSOLE_WRITELINE(FORMAT$(t1-t0, "#0.00000")) '---Wait for a key to stop execution CONSOLE_WAITKEY OpenGl graphicsHere a sample working with TBGL module, thinBasics OpenGl module developed by Petr Schreiber using the thinBasic SDK. Just a rotating triangle but have a look at TBGL script in our forum and you will remain astonished. USES "TBGL" '---Load TBGL module USES "UI" '---Load User Interface module DIM hWnd AS DWORD '---This will contain handle of the window '---Creates OpenGL window, it returns handle hWnd = TBGL_CreateWindow("Rotating triangle - press ESC to quit") TBGL_ShowWindow '---Shows the window TBGL_GetAsyncKeyState(-1) '---Resets key status before checking WHILE TBGL_IsWindow(hWnd) WIN_setTitle (hWnd, " ESC to quit (" & TBGL_GetFrameRate & " FPS)") TBGL_ClearFrame '---Prepares clear frame TBGL_Camera 0,0,5,0,0,0 '---Setups camera to look from 0,0,5 to 0,0,0 TBGL_Rotate GetTickCount/10,1,1,1 '---Rotates around all axis TBGL_BeginPoly %GL_TRIANGLES '---Starts polygon definition based on triangles TBGL_Color 255,0,0 '---Sets RGB color - Red TBGL_Vertex -1,-1,0 '---Adds vertex TBGL_Color 0,255,0 '---Sets RGB color - Green TBGL_Vertex 1,-1,0 TBGL_Color 0,0,255 '---Sets RGB color - Blue TBGL_Vertex 0, 1,0 TBGL_EndPoly '---Ends polygon definition TBGL_DrawFrame '---Swaps the buffers - displays rendered image IF TBGL_GetAsyncKeyState(%VK_ESCAPE) THEN EXIT WHILE WEND TBGL_DestroyWindow '---Closes OpenGL window MSGBOX 0, "Show is over", %MB_ICONINFORMATION or %MB_TOPMOST, "TBGL demo" This particular module, TBGL does not offer just 1:1 translation of handy OpenGL commands, it does internal garbage collection, texture loading, model handling and animation too for example. TBGL (thinBasic Graphic Library) uses it's own file format for 3D models called M15. Never heard of it? Files of this kind are produced by thinEdge, 3D editor developed especially for cooperation with thinBasic. And if you don't like this modeler or just don't want to learn another program more? What about model exporter for Blender application developed by Michael Hartlef (a Blender script create specifically to export Blender 3D models directly into M15 format), or taking advantage of thinEdge OBJ import ability? Wings3D, GMax ... you know them. Any modeler capable of producing OBJ files can be used to create art for your next thinBasic game. Script ExecutableJust recently we started development of thinBundle. It is still in its early stage but results seem really good. Using thinBundle, thinBasic users will be able to create independent thinBasic script executables. thinBundle IS NOT A COMPILER. No machine code will be produced. thinBundle will create a kind of closed, compressed, crypted executable file containing all the resources a script needs in order to be executed without having thinBasic installed in the target machine. The .exe file produced will be like a box containing all the files needed to execute the script (dll, modules, sources, thinBasic exe, ...). When executed, all needed files will be extracted on disk in the same directory of the exe. All files will be system hidden. After execution, all extracted files will be deleted. ConclusionsWe hope this article expresses the power and simplicity of thinBasic. You will need to try it out to experience the other big feature thinBasic can give you. Just one final word on thinBasic execution speed. thinBasic is fast! Every new thinBasic version has some improvement on script execution speed. We continually strive to improve optimizations and many users are surprised by the performance of this scripted language, most times it feels like the performance from a compiled application. References
Website: http://www.thinbasic.com |
||||||||||||||||||||||
Epic Crusade by Jare |
||||||||||||||||||||||
Epic Crusade is an RPG game project like Final Fantasy and Chrono Trigger and it is programmed with CoolBasic. The story begins so that the game's main character Rei is sitting in his home and he decides to leav his small house and go to find some adventures like beating dragons and monsters and so on. But then his granpa appears and commands him to go get a special herb from a cave for the town-healer so he could make some medicine out of it. The medicine is needed for grandpa's sore back. Grandpa gives Rei a little money. Rei has to go to buy some equipment from a nearby town so he could start a dangerous trip inside the cave for the herb. At this point the project is at early development stage since its first introduction was on 6th of November in 2006. There is not yet very much information of this project but a little test version of the game proves that this is going to be one of the best RPG's coded with CoolBasic. Referring to the test version and screenshots, the game has great retro style graphics and effects. The fighting system is turn-based. You select the attack you want to use, then you point the attack to the enemy you want. After you have done your attack the enemies attacks you one by one against you. As the game advances you will get multiple characters into your party and the battles will become more strategical. If you like some old school RPG games, you should try this one. The classical concept works in this game project and you just cannot wait until the developers get his master piece finished. See the links below! Links referred to the game project:Direct link to the test version: You can find some screenshots of the game at: The game story: Discussion about the project (unfortunately only in Finnish): |
||||||||||||||||||||||
|
||||||||||||||||||||||
A piece of history - Star Trek Game: by E.K.Virtanen |
||||||||||||||||||||||
To boldly go...In 1971, Mike Mayfield probably didn't know what he was starting when he wrote his very first Star Trek game. In the course of the following year, he had already ported it to Hewlett Packard BASIC. In 1973, David Ahl translated it to DEC BASIC and soon after that, with Mary Cole he had it ported for RSTS-11 (BASIC PLUS). In the same year, the game was also publishedint the very first edition of 101 BASIC Computer Games (David Ahl; July, 1973). Soon after releasing source of this game in that book, various peoples started translating this game for multiple different computers and operating systems. To see the "consequences" of Mike Mayfield's game, we need to use an time line of the more known versions of this game in the 1970s.
The information listed above is just the tip of the iceberg. Numerous variations and translations were made back in the 1970s. Back in those days, games were considered as total waste of computing time so administrators usually removed games when they spotted them. After 70's:In the 80's, 90's and even in this millenium, there has been published new versions of this, probably one of the most ported games ever.
Eventhough i mention only four versions of this game here, it certainly does not mean that was all of them. Dozens of other variations are out there somewhere. Just search for them if you're interested. Related Links:
|
||||||||||||||||||||||
The Evolution Of BASIC: by Stephane Richard (MystikShadows) |
||||||||||||||||||||||
INTRODUCTION:From the very start BASIC (Beginner's All purpose Symbolic Instruction Code) has always represented a language for anyone wanting to do programming. This was true wether the user was indeed a software developer or not. It was a language that has always been fun to use and quickly allowed a solution to a given problem to be created. Looking at what BASIC was when it was created and where it stands today (in it's many implemented dialects). I have decided to define my vision of what BASIC will be (maybe should be) in the future. There's alot of different reasons certain things should be present in the language and we'll try to see what could be added to help the evolution of BASIC. Before we do that, let's take a look and what basic is, when it started and take it from there. BASIC THE BEGINNING:BASIC was created in 1963 by by John George Kemeny and Thomas Eugene Kurtz at Dartmouth College. The very first BASIC was hence named Darthmouth BASIC. It was when this first dialect of BASIC was made available that the eight principle of BASIC design were created. These principles were:
Back then, BASIC had line numbers. These line numbers essentially governed the sequence of instruction to execute. It had branching such has GOTO and GOSUB to jump to different parts of the program as needed by the current structure of the program. Since back then, computers didn't have alot of memory the complexity of the programs that could be made were quite limited. But back then the need for computer software was also very limited in size and complexity. THE HISTORY OF BASIC'S EVOLUTION:Since it's first implementation, BASIC has gone through many additions and changes that made it the BASIC we are accustomed to seeing today. With the decades, the need for more complex programs that manipulated more data in more complex ways was getting more and more obvious. To follow the trends, basic was given more memory to work with (which allowed it to work on a bit more complex programs) to answer the needs of the era. In the 70s different languages surfaced which seemed to be able to deal with bigger more complex programs and hence started being used more than BASIC. To accomodate that commands to execute more than one module from within a main source program were added to basic. Commands such as RUN, SHELL and CHAIN opened up new opportunities to create more complex programs in BASIC. But again BASIC didn't quite fit the bill as even more complex applications were starting to be in demand. In the 80s BASIC started to do away with line numbers and offered a more modular approach to program development. The notion of SUBs and FUNCTIONS were added thus practically eliminating the need for the infamous GOTO statement which was the cause of the classic "spaghetti code" trend that had started. Not too far after that BASIC gained the ability to seperate code into different modules which helped the overall organization of programming projects a whole lot. Not too long after that, a new trend in programming became popular (quite fast). Object Oriented Programming was one of the newer methodologies of the 80s and offered many advantages to complex programming projects that still today cannot be denied (on certain types of projects). OOP was hard to implement in BASIC while keeping true to the eight design principles of BASIC. So it wasn't until much later in the history of programming languages that OOP got added to some of the BASIC dialects. Of course the need for compiled code also became apparent as better performances were expected of a language like most other features getting added. With the popularity of Windows growing in the late 80s / early 90s. A new notion called "event driven programming" started to manifest itself. BASIC gained features to help it deal with even driven programming. Products such as Visual BASIC for DOS and Windows appeared offering alot of what today's VB programmers are accustomed to. Controls on a form had certain properties and handle different types of events. And thus BASIC became a true event driven programming language. BASIC AS IT STANDS TODAY:BASIC evolved based on the needs and types of software development projects that were needed over the years. BASIC can now work with many mathematical functions integrated into the language. it has some good standard string manipulation functions as well. Event Driven Programming is still in there and typically rather easy to use. BASIC is now the result of the needs imposed by those needed certain types of programs developed. AS such, Database have been added to the repertoire of applications that can be developed with basic. All in all BASIC has become a true "all purpose" language but not without some sacrifices. To use these new features some complexity were added to the language. The BASIC learning curve is growing. since you can do things in BASIC today that you simply couldn't do before. For example alot of BASICs now handle pointers and pointer arithmetics. This is a complex notion in itself that is hard to simplify to the level that the eight design principles of BASIC would hope them to be. As such, the learning curve gets affected when these new features get added. However, these features are quite needed and cannot be ignored. Today, people want to see OpenGL, DirectX, music and multimedia programs of all kinds. Hence all this does need to be present in a language if the language is to make it's mark in any way. OOP is still optional but fast almost becoming a mandatory feature of a language. With all these new needs of today's users, BASIC needs to have them for today's needs and for the future as well. THE FUTURE OF BASIC:Of course, this is my own vision of the future of BASIC. I believe that you can only add so much to a language without changing the learning curve. However, the need to add to the language grammar itself is obviously present. So how can we counteract this newly added complexity in the future? How can we help keep BASIC simple to use while adding these complex notions and features to the language? I believe there are three ways to do just that.
With these 3 principles in place I believe it will be more than possible to add any complex notion or feature to a BASIC dialect while following the eight design principles of BASIC as a language. It will also allow the language and the IDE to adapt to a given user's level of knowledge and help the IDE adapt to a user's way of working with the language. IN CONCLUSION: (THE BOTTOM LINE):BASIC should remain a language anyone can "quickly" learn and use. It definately should incorporate whatever feature that is in demand at the time since this helps BASIC be an "all purpose" programming language. It should continue to typically be the first language of any new programmer because it should remain the most "immediately" rewarding language. Hence have the ability to code things fast in it to get fast results without predefined structures or concepts to learn before coding. Any new additions should typically be evaluated against the
eight design principles of BASIC atleast to a minimum just to help keep
BASIC in the confines of it's definition. Use of clear english like
keywords
instead of symbols would help alot for example. BASIC is a
real language where saving keystrokes should be the job of the IDE, not
the language. With all this in mind I see a great bright future for
BASIC and
I am open to discussions about it as well. Just email me with any comments and suggestions and we'll talk about it. Until next time, Happy reading, learning and coding. |
||||||||||||||||||||||
~ TUTORIALS ~ |
||||||||||||||||||||||
Programming Simulation Games: by Stephane Richard (MystikShadows) |
||||||||||||||||||||||
Introduction:The best way to begin this tutorial on programming simulation games is to define exactly what a simulation game is. Tim Hartnell, in his 1986 book entitled Creating Simulation Games On Your Computer, offers the best definition of what a simulation is: "A simulation is a computer model of cause and effect. Event A is linked to event B by equation X. Modify B and C is affected by linking factor Y.". He then gives a simple example that goes like this: CAUSE ----------> EFFECT --------------> EFFECT SWITCH ON CURRENT FLOWS LIGHT GLOWS This is of course a very simple model. But then again a simulation shouldn't be confused with the system it simulates. There are all kinds of simulations that we can find out there. They range from very simple simulations to highly advanced ones. For example, a flight simulator. The first thing to remember is that a simulation is a simplified model of the system or situation it is simulating. Stock Market simulations are another wide spread use of simulations. The best reason for the existance of simulation is that it allows you to experience high risk situations without causing any harm to anyone (especially yourself) or anything. For that reason simulations have been playing an important role in our recent history. This tutorial will teach you the components of a simulation as well as a complete example of a simulation game (code and sample execution) so that you can get a feel of how these beasts work. Of course the example will be very simplified for the sake of this tutorial, but it will however include all aspects of a simulation game. So let's get started shall we? The Types Of Simulations:There are as many types of simulations as they are systems to be simulated. Physical items based simulations, people / population based simulation, real world situations (crisis or not) and so on. But in all cases, one thing we can notice is that all possible simulations fall into two groups. Each of these group represent different types of programming challenges, each have they use and their role in the world of simulations.
Of course, in a game, anything can happen and it wouldn't exactly be beyond the scope of reality to include a combination of these two types of simulation to add challenge to the game. But typically, one of these two can offer plenty of challenge in itself. It's therefore important to plan the simulation ahead of time, figure out which group of simulation it falls under and determine, before you start coding, which type of data or process takes precedence over the rest of the simulation. Then the factors that can influence this data can be evaluated to see how it could/should affect the data as in if this influence is good or bad to the expected results of the simulation. A little planning goes a long way in this type of game. Before we start coding anything, I'll start by explaining the components of a simulations. These are the different parts of a simulated system that either play a role in the outcome of the simulation or setup the complete system that is being simulated depending on the type of simulation being created. The Components Of A Simulation:In order to create a simulation, certain core elements need to exist to make it a complete simulation system. In essence, creating a simulation is like creating a small world. In that world, you need certain elements to call it a world and you need certain things to happen to call your world a simulation. Let's review these elements of a simulation.
As you can see, all these factors will play an important part in most simulations you'll be making. Of course, based on the type of simulation and what one is trying to get out of the simulation not nevessarily all of these components will be needed. But in most cases, it's good to plan to have all of them (as a simulation template if nothing else) as they are typically all used. The Life (Predator And Prey) Simulation Elaborated:With this knowledge in mind, we can now begin to create our simulation. In the context of this tutorial we will create a rather simplistic life simulation. There will be predators and preys. As you might have guessed, the predators eat the preys. The object of this simulation will therefore be to keep the life of both predators and preys in balance so that there are always preys to feed on and always predators present to eat the preys. In this simulation, If there's not enough preys, the predators will eat them all up and then die of starvation. If there are too many preys, the predators will eat more preys and new predators will be born. The idea is to find the real ideal number of predators and preys to keep the simulation running for as long as possible. The only user interaction will be to allow the user to specify the number of predators and preys to begin the simulation with. The simulation will then loop until atleast one of the two (predator or prey) dissapear (count down to 0). How many preys predators eat in a cycle, how many new preys and predators are created I will leave to random to make it a bit harder to find those ideal numbers. These will change every time you run the program. But on each run you can play with different numbers so during that one session of running the simulation the number of preys eaten and so on will not change. So let's start to create some code for this. Coding For The Predator/Prey model:As you'll see from the code we'll create it will be a rather simple simulation but I will be giving tips along the way in case you want to make it more complex. The first thing we'll do is define a user defined type that we will use to generate a simulation report after a simulation is ended. This will essentially be generated as the simulation runs so for each time cycle a new entry will be added to an array we'll declare later of this user defined type. As usual, you don't have to fool around with cut and pasting the code shown here, you can get it all right here, already typed and ready to go. Though I used FreeBASIC for this tutorial, this simulation should work on any basic that supports the RANDOMIZE and RND() statements. If your BASIC doesn't have those, chances are they have an equivalent so take a look at the help file and just replace these two statements with their equivalent in your flavor of BASIC. ' ---------------------------------------------- ' NAME: SimulationData ' DESCRIPTION: Holds information about each ' run cycle of a given simulation ' ---------------------------------------------- TYPE SimulationData CycleNumber AS INTEGER TimeMark AS INTEGER PredatorCount AS DOUBLE TotalPopulation AS DOUBLE PopulationDifference AS DOUBLE DifferencePredators AS DOUBLE PercentagePredators AS DOUBLE PreyCount AS DOUBLE DifferencePreys AS DOUBLE PercentagePreys AS DOUBLE END TYPE There this should be sufficient information about the simulation to be able to extract some useful information from the simulation results. of course now, we will need variables including an array that will hold the information of the simulation. The other variables will be to hold the initial simulation parameters and the results of the formulas we will be using to determine the new population. Here are the variables. ' --------------------------------------- ' Globally Shared Variable Declarations ' --------------------------------------- DIM SHARED LongestRun AS INTEGER DIM SHARED AggressiveFactor AS DOUBLE DIM SHARED TotalPopulation AS DOUBLE DIM SHARED NumberOfPredators AS DOUBLE DIM SHARED NumberOfPreys AS DOUBLE DIM SHARED RunCount AS INTEGER DIM SHARED Counter AS INTEGER DIM SHARED SimulationRuns() AS SimulationData LongestRun will be used to monitor the longest run reach so far in a session. AgressiveFactor will be used to determine how agressive the predators are vursus the preys. NumberOfPredators and NumberOfPreys will hold the results of the formulas during the simulation. RunCount jus tells us which cycle we are currently in. finally, SimulatioRuns is the array that will hold results of the simulation for each run. The next step in our simulation will be to setup the initial data and variables. Basically.The agressive factor will be asimple randomly generated value from 0 to 1. The starting numbers of predator and preys will be what the user needs to enter into the system. and we'll also initialize the first element in our array to hold the initial data entered by the user. ' -------------------------------------------- ' Set up all initial data for the simulation ' -------------------------------------------- RANDOMIZE TIMER RunCount = 1 AgressiveFactor = RND(1) ' ------------------------------------ ' Inquire for the initial population ' ------------------------------------ INPUT "Enter the number of Predators: "; NumberOfPredators INPUT "Enter the number of Preys: "; NumberOfPreys ' ------------------------------------------------------- ' Prepare the array for it's initial data and assign it ' ------------------------------------------------------- REDIM SimulationRuns(1 TO RunCount) AS SimulationData SimulationRuns(RunCount).CycleNumber = RunCount SimulationRuns(RunCount).TimeMark = 0 SimulationRuns(RunCount).TotalPopulation = NumberOfPredators + NumberOfPreys SimulationRuns(RunCount).PopulationDifference = 0 SimulationRuns(RunCount).PredatorCount = NumberOfPredators SimulationRuns(RunCount).DifferencePredators = 0 SimulationRuns(RunCount).PercentagePredators = NumberOfPredators * 100 / TotalPopulation SimulationRuns(RunCount).PreyCount = NumberOfPreys SimulationRuns(RunCount).DifferencePreys = 0 SimulationRuns(RunCount).PercentagePreys = NumberOfPreys * 100 / TotalPopulation At this point we are ready to run the simulation itself. Remember that if we run out of predators or preys the simulation will stop since both are needed for the simulation to work. So it won't be a loop where we know how many times will will be looping. As such we will have to loop while neither of them is 0. The important thing to note in this next code section is the two formulas that calculate the number of population for predators and preys. ' ---------------------- ' Main Simulation Loop ' ---------------------- DO WHILE NumberOfPredators > 1 AND NumberOfPreys > 1 ' --------------------------------- ' We first Increment the RunCount ' --------------------------------- RunCount = RunCount + 1 ' ----------------------------------------------------------- ' Next we calculate the new populations ' Note you can play with these formulas to see what happens ' ----------------------------------------------------------- NumberOfPredators = NumberOfPredators + _ ((8 * NumberOfPredators - _ NumberOfPredators * NumberOfPreys / 3) * _ AggressiveFactor ) NumberOfPreys = NumberOfPreys + _ ((4 * NumberOfPreys - _ NumberOfPreys * NumberOfPredators ) * 0.01 TotalPopulation = NumberOfPredators + NumberOfPreys ' -------------------------------------- ' Next we add the results to our array ' -------------------------------------- SimulationRuns(RunCount).CycleNumber = RunCount - 1 SimulationRuns(RunCount).TimeMark = RunCount - 1 SimulationRuns(RunCount).TotalPopulation = NumberOfPredators + NumberOfPreys SimulationRuns(RunCount).PopulationDifference = SimulationRuns(RunCount -1).TotalPopulation + _ ( NumberOfPredators + NumberOfPreys ) SimulationRuns(RunCount).PredatorCount = NumberOfPredators SimulationRuns(RunCount).DifferencePredators = SimulationRuns(RunCount - 1).PredatorCount - _ NumberOfPredators SimulationRuns(RunCount).PercentagePredators = NumberOfPredators * 100 / TotalPopulation SimulationRuns(RunCount).PreyCount = NumberOfPreys SimulationRuns(RunCount).DifferencePreys = SimulationRuns(RunCount - 1).PreyCount - _ NumberOfPreys SimulationRuns(RunCount).PercentagePreys = NumberOfPreys * 100 / TotalPopulation LOOP We're nearing the end of the code right now. The next small part is to adjust the LongestRun variable if the current simulation ran for more cycles than any previous one. This is done with the following simple piece of code: ' --------------------------------- ' Adjust The Longest Run Variable ' --------------------------------- IF RunCount > LongestRun THEN LongestRun = RunCount - 1 END IF The next step is displaying the simulation report to the user. We'll start by clearing the screen. We will then display the report header and initial data for the current simulation. Here is the code to do that: ' ------------------------------- ' Display The Simulation Report ' ------------------------------- CLS ' --------------------------- ' Display The Report Header ' --------------------------- PRINT " =========================================================================" PRINT " S I M U L A T I O N R E P O R T" PRINT " =========================================================================" PRINT PRINT " Aggressiveness Factor.......: "; PRINT USING "###.#####"; AggressiveFactor PRINT " Initial Predator Population.: "; PRINT USING " #,###"; INT(SimulationRuns(1).PredatorCount) PRINT " Initial Prey Population.....: "; PRINT USING " #,###"; INT(SimulationRuns(1).PreyCount) PRINT We'll follow that with the printing of the column headers of the report. In this case everything is already adjusted to line up the values with the column headers. If you were to write your own reporting section. It would be good to give it a few runs to make sure everything is ligned up so the report looks good. Here is the code for the displaying of the column headers for the report. ' ---------------------------- ' Display The Column Headers ' ---------------------------- PRINT " =========================================================================" PRINT " CYCLE TOTAL PREDATORS PREYS PERCENTAGES PRINT " COUNT POPULATION TOTAL DIFFERENCE TOTAL DIFFERENCE PREDATORS PREYS PRINT " -------------------------------------------------------------------------" Next comes the loop that will go through the elements of the SimulationRuns array to display each of the results in the report. As you can see here I am using the PRINT USING statement to keep all numbers right justified. I think right justifying numbers in a report helps the report look clean and that much more readable since we are reading numbers. Here is the code for this loop. ' ----------------------------------------------- ' Loop through the array to display the results ' ----------------------------------------------- FOR Counter = 1 TO UBOUND(SimulationRuns) PRINT USING " ##### ";Counter - 1; PRINT USING " ##### "; SimulationRuns(Counter).TotalPopulation; PRINT USING " ##### "; SimulationRuns(Counter).PredatorCount; PRINT USING " ##### "; SimulationRuns(Counter).DifferencePredators; PRINT USING " ##### "; SimulationRuns(Counter).PreyCount; PRINT USING " ##### "; SimulationRuns(Counter).DifferencePreys; PRINT USING " ###.##%"; SimulationRuns(Counter).PercentagePredators; PRINT USING " ###.##% "; SimulationRuns(Counter).PercentagePreys NEXT Counter PRINT " =========================================================================" PRINT Finally, the last thing to do is display the longest run to date to the user and simply ask them if they want to run another simulation. Answering Y to this question will keep the Agressiveness Factor the same which will give the user the ability to test different population values for this particular aggressiveness factor to see how long they can keep the simulation going. Here's the final piece of code. ' -------------------------------------------- ' Display The Longest Simulation Run To Date ' -------------------------------------------- PRINT " The sest simulation, so far, ran for " + STR$(LongestRun) + " cycles." PRINT ' -------------------------------------------------- ' Enter Loop To Inquire for another Simulation Run ' -------------------------------------------------- DO WHILE Answer = "" OR (UCASE$(Answer) <> "Y" OR UCASE$(Answer) <> "N") INPUT " Run another simulation? (Y/N) "; Answer IF UCASE$(Answer) = "N" THEN CanExitSimulation = -1 END IF LOOP LOOP And there you have it. Our program is over and ready to execute. As you can see, the code itself isn't all that complicated in this project. Everything really revolves around the agressiveness factor and the two formulas to calculate the new population for the predators and the preys. The rest of the program is essentially book keeping work. Sample Simulation Executions:Ok, now that we have our program it's time to give it a first test run. I compiled the program and executed it. It gave me an aggressiveness factor of 0.16597 and asked me for the number of predators and number of preys. In this first run, I entered 30 predators and 30 preys, a nice round number for starting a simulation. Here is the simulation report that it gave me: ========================================================================= S I M U L A T I O N R E P O R T ========================================================================= Aggressiveness Factor.......: 0.16597 Initial Predator Population.: 30 Initial Prey Population.....: 30 ========================================================================= CYCLE TOTAL PREDATORS PREYS PERCENTAGES COUNT POPULATION TOTAL DIFFERENCE TOTAL DIFFERENCE PREDATORS PREYS ------------------------------------------------------------------------- 0 60 30 0 30 0 50.00% 50.00% 1 45 20 10 25 5 44.31% 55.69% 2 40 19 1 21 4 46.58% 53.42% 3 39 21 -3 18 4 54.58% 45.42% 4 42 29 -7 13 4 68.23% 31.77% 5 53 46 -17 8 6 85.38% 14.62% 6 88 86 -41 1 6 98.44% 1.56% 7 193 195 -108 -1 3 100.64% -0.64% ========================================================================= The best simulation, so far, ran for 7 cycles. Run another simulation? (Y/N) ? What this report mean? Let's take a look in details. We can see that for the first two cycles the population of predators was going down and so was the population of preys (but as you can see, the prey population went down continuously throughout the whole run of this simulation. At the third cycle the number of preys was abundant enough for the predators to reproduce (according to their aggressiveness factor) which turned the tables around and began augmenting the predator population. More predators need more preys to eat in order to survive and that's exactly what they did and you can see that by the increased drop in population of preys quantity. At the end of the simulation, all the preys vanished which means that the predators eventually died of starvation. I then answered yes because I wanted to run another simulation (with the same aggressiveness factor). In this second run I entered 20 predators and 30 preys just to see what would happen. What do you believe would happen in tis second simulation? Well, let's have a look at the simulation report that got generated from this second run: ========================================================================= S I M U L A T I O N R E P O R T ========================================================================= Aggressiveness Factor.......: 0.16597 Initial Predator Population.: 20 Initial Prey Population.....: 30 ========================================================================= CYCLE TOTAL PREDATORS PREYS PERCENTAGES COUNT POPULATION TOTAL DIFFERENCE TOTAL DIFFERENCE PREDATORS PREYS ------------------------------------------------------------------------- 0 50 20 0 30 0 40.00% 60.00% 1 41 13 7 27 3 32.95% 67.05% 2 36 11 2 25 2 30.32% 69.68% 3 34 10 1 24 2 30.11% 69.89% 4 33 10 -0 22 2 31.86% 68.14% 5 32 11 -1 21 2 35.70% 64.30% 6 32 14 -2 19 2 42.23% 57.77% 7 34 18 -4 16 3 52.38% 47.62% 8 38 25 -8 13 3 66.84% 33.16% 9 49 41 -16 8 5 84.01% 15.99% 10 80 78 -37 2 6 97.48% 2.52% 11 172 174 -95 -1 3 100.82% -0.82% ========================================================================= The best simulation, so far, ran for 11 cycles. Run another simulation? (Y/N) ? First thing you'll notice is that the second simulation ran four cycles longer than the first one. Is that what you anticipated would happen or did it go completely against what you were originally thinking? As you can see here, it wasn't until the 5th cycle than the predator population started to rise thus eating more and more preys bringing them right down to their extinction. You can finally also notice that once the predator population started to rise, that it took more cycles than before to eat up all the preys. What does all this tell you? That the right balance of preys predator can help with the existence of both (not just the predators per se). How Things Could Be Done DifferentlyThere are, of course, many things that we could have coded differently. This is, after all, a very simplified simulation model. Let's take a look at three of the things that we could have done differently.
In essence, everything depends on what you are simulating, Which group of simulation it falls under and of course how close to the real world you want it (or need it) to be. In the case of flight simulators aimed at training future pilots, you would typically want that simulation to be as close as possible to the real thing. And you'd also want a whole like of unpredictable factors to come into play of the future pilot's training (like landing on a bridge in the middle of a hurricane for example) if that's what it takes to keep the crew and passengers alive, wouldn't you be glad that he got that in his training? I thought so. And For The Final WordWith this tutorial I really only touched the very tip of the iceberg. It's surprising how complex simulations can get no matter which group of simulations they fall under. Now if you were to make a simulation like the one shown here, it depends a little bit of planning ahead. But, if you are looking at making a full fledged flight simulator, It would of course be highly recommended that you sit down for a while and get a lot of initial data and formulas before even starting to code. I'm always open to discussions and suggestions about this or any of my other tutorials. If you have ideas and suggestion for possibly a 2nd part to this tutorial, feel free to let me know about it. Simulation can go in all directions, on all types of subjects and to all degrees of complexity. So the sky really is the limit as far as simulation goes. So i am open to new ideas all the time. Until next time, I hope this tutorial was clear, but if you have a question, don't hesitate to ask me. Until next time, Happy reading, coding and in this case, happy simulating. |
||||||||||||||||||||||
Basic4GL Tutorial; Tile Maps: by Linkage |
||||||||||||||||||||||
So, you know how to use sprites, and want to make your own 2D game. But most of the time, such a game will require a level to move around, and you're not sure how to make it. You COULD make it one big sprite, or heaps of sprites put together, but that'd be annoying, and would probably slow the game down. So what's a good way to make levels? Tile Maps. Tile Maps are very similar to sprites, but are generally meant to be bigger. and don't require making a huge sprite. Instead, you take a picture that has multiple segments, referred to as tiles, and take each segment and place them where you want, kind of like a puzzle. This way, we can make a map using as little as 2 tiles. So how do we make these Tile Maps? This tutorial will show you how, providing sample code and explanations of how it works to give you a good understanding of them. You don't really need to know too much about Basic4GL to get through this tutorial, but an understanding of the main basic things such as loops, variables etc. Is required. OK, so here we go. First, we need a picture to use as our tiles. For now, we'll just use a very simple one, with only 2 tiles. Here it is: you'll need to save this picture into whatever directory you're running the finished program from. As you can see, it's just divided into black and white sections. Seeing as the default background for Basic4GL programs is black, we're going to use the white area to show where something is, and the black area for blank space. Now, we're going to write a section of code that we'll use later on to tell Basic4GL how to distribute the tiles for the Tile Map. For this we use a data table: TileData: data 9,5 data 1,1,1,1,1,1,1,1,1 data 1,0,0,0,0,0,0,0,1 data 1,0,0,0,0,0,0,0,1 data 1,0,0,0,0,0,0,0,1 data 1,1,1,1,1,1,1,1,1 If you've never seen the data command before, it is basically used to tell Basic4GL that anything after it is going to be read into the program later and used accordingly. Now, from looking at the data there, we can see the general shape of a room, visualising the 1s as white space and the 0s as black space. It is useful when using data tables for tile maps to keep all the numbers aligned, so it makes it easier to see in the numbers your map. However, when you start using pictures with an amount of tiles that goes into double digits, they may become unaligned and harder to visualise. It's obviously not very good to restrict the variety of a tile map simply so that you can code it easier, so you'll have to either put up with it or leave the first 10 spaces blank, so that all of the tiles will have double digits (and if you go into triple digits, well... that's one big Tile Map!). Also, you may be wondering why we have the 9 and the 5 up the top. We're going to use that laster to help tell the program just how much data to read. Now, we have to actually store that data into a variable so that we can use it. For that we have to dim a few variables and go through a certain subroutine: dim &tiles ()(), mapx, mapy, i, x, y LoadTiles: read mapx, mapy alloc tiles, mapx -1, mapy - 1 for y = 0 to mapy - 1 for x = 0 to mapx - 1 read i tiles (x)(y) = i next next return You're probably a bit puzzled as to how this works, so I'll explain it bit by bit. First, we dim a pointer variable. I don't know much about pointer variables, so I can't go into a proper explanation of them (although anyone who can and is willing to contribute one to this tutorial... please go ahead), but they must be dimmed with a & at the start, and the type we are dimming, which is going to have a 2D array of numbers, must have a ()() at the end. The other variables we are dimming are all integer variables. OK, now to the more confusing bits. First, we use read. Read does more or less what it says- it reads data, starting from the top, and assigns the values it reads to the variables told. So in this case, it first reads the data 9, and assigns it to mapx, and then the 5, and assigns it to mapy. So now mapx = 9 and mapy = 5. Then, we use alloc. We use this to allocate the values of mapx 1 and mapy 1 to the array dimensions of &tiles. So now, &tiles has the dimensions of (8) and (4). This means that it is divided up into 8 sections, each with 4 values. Now we use two for loops to read the rest of the data. Because when we go through the first loop the first time, it executes all of the second for loop, in which it reads the next piece of data into i, and ends up doing that instruction the amount of times equal to 8 times 4, which equals 32. So that way, we get it to read all of the data we put in. Also in the second for loop is an instruction to make tiles (x)(y) equal the current value of i. So we end up storing all of our data values into tiles, which we will now use to make the actual map appear. So after that code we place this: MakeMap: tilemap = LoadImageStrip("basictiles.png", 32) gosub LoadTiles map = NewTileMap(tilemap) SprSetYRepeat(false) SprSetXRepeat(false) SprSetTiles(tiles) And we add some more variables to our dim statement: dim &tiles ()(), mapx, mapy, i, x, y, tilemap(1), map And one line of code after that dim statement: goto MakeMap To end up with a working program, which is this: TileData: data 9,5 data 1,1,1,1,1,1,1,1,1 data 1,0,0,0,0,0,0,0,1 data 1,0,0,0,0,0,0,0,1 data 1,0,0,0,0,0,0,0,1 data 1,1,1,1,1,1,1,1,1 dim &tiles ()(), mapx, mapy, i, x, y, tilemap(1), map goto MakeMap LoadTiles: read mapx, mapy alloc tiles, mapx -1, mapy - 1 for y = 0 to mapy - 1 for x = 0 to mapx - 1 read i tiles (x)(y) = i next next return MakeMap: tilemap = LoadImageStrip("basictiles.png", 32) gosub LoadTiles map = NewTileMap(tilemap) SprSetYRepeat(false) SprSetXRepeat(false) SprSetTiles(tiles) So, if you run that, you can see the results, but first let me explain how the code we added works: MakeMap: tilemap = LoadImageStrip("basictiles.png", 32) gosub LoadTiles map = NewTileMap(tilemap) SprSetYRepeat(false) SprSetXRepeat(false) SprSetTiles(tiles) This area first assigns the variable tilemap the Image Strip of our tile picture. Then, we use gosub, which tells the program to skip to another labelled area of the program and run the code from there until it hits a return command, at which point it goes back to where it was. In this case, it sends it to the LoadTiles subroutine, where all the values of &tiles are set. Then, we use NewTileMap to make map a Tile Map, with the tiles in tilemap. SprSetXRepeat and SprSetYRepeat stop the map from being continuously displayed in both X and Y directions. Then we use SprSetTiles to set the map's tiles to those indicated in &tiles, at which point it displays it. So, hopefully this tutorial has given you a good understanding of how to make Tile Maps. If not, let me know and I'll either try and address your questions personally or edit the tutorial to fit your needs. The most common thing I could think of is that maybe my explanations in some parts were a bit vague/confusing. I'm also planning on making another one or two tutorials to do with Tile maps, such as collision detection with them. EXTENSION: Loading Multiple Tile Maps Loading multiple Tile Maps is not much different from loading a single tile map. For our example, we are simply going to add a second data table and make some changes to the section of code that makes the maps. Here's the second data table: TileData2: data 7, 4 data 1,1,1,1,1,1,1 data 1,0,1,0,1,0,1 data 1,0,1,0,1,0,1 data 1,1,1,1,1,1,1 You should place that under the previous data table. And here's the changes we need to make to the part that makes the maps: MakeMap: tilemap = LoadImageStrip("basictiles.png", 32) reset TileData gosub LoadTiles map(0) = NewTileMap(tilemap) SprSetYRepeat(false) SprSetXRepeat(false) SprSetTiles(tiles) reset TileData2 gosub LoadTiles map(1) = NewTileMap(tilemap) SprSetXRepeat(false) SprSetYRepeat(false) SprSetTiles(tiles) SprSetPos(300,100) We also need to slightly change part of our dim statement, too, so that map looks like map(1). So, what difference has our changes made? If you've run that, you'll see that it displays two Tile Maps in different sections of the screen. We do this by, apart from adding a second section to make a map, by adding in the reset function. The reset function resets the spot from which the program will read data to the label you tell it to. This is useful when you need the program to read sections of data from different places in the program. In this particular program, it's not actually necessary, but in proper 2D games it's important to have it before every time you run the LoadTile routine, as you will probably end up having to read certain sections of data multiple times. So by placing these commands in front of every time you run the LoadTiles routine, we make sure that the data we want to be read is read. There is also one more function at the end of the program: SprSetPos. This just moves our second tile map to the designated position on screen, so we can see both at the same time. Some changes that could be made to this program is to, while having multiple tile maps, to only display one at a time. Apart from a small section to decide which one to display, it's also good to add in some more pointer variables, so that rather than having multiple map-making sections, we only add an if statement to the section that sets its tiles. For this we'd have to add a line to, with the new pointer variables, set the pointer variable you want to mirror the current &tiles after each LoadTiles routine. But, I'll let you give that a try for yourself. |
||||||||||||||||||||||
Introduction to the FreeBasic Extended Types: by Rick D. Clark |
||||||||||||||||||||||
INTRODUCTION:FreeBasic is moving towards implementing Object Oriented programming. While classes have not yet been added to the language, the Type definition has been extended to include some Object Oriented constructs as a first step towards full class support. This article introduces some of the concepts of Object Oriented design and explains some of the extended type constructs. GETTING STARTED:In order to use the new type constructs, you will need to download the CVS version of the compiler; Windows, Linux or DOS. You select the large version if you are updating for the first time. If you have not done so, download and install the last stable .17 release that you will find on the FreeBasic download page. Once .17 is installed, then unpack the CVS version in the same install folder, overwriting all files. OBJECT ORIENTED PROGRAMMING:Object Oriented Programming, usually shortened to OOP, is a methodology that enables the programmer to build code units called objects. An object is a thing; it is a unit of code that represents something that needs to be manipulated in a program. You can think of an object as a noun: a person, place or thing. An object could be a sprite, a drawing primitive or something more elaborate like a tank in a game. Any concrete entity that has a set of characteristics and actions can be represented as an object. An object contains both the data needed by the object, and the methods (subroutines and functions) that act on the data. This grouping of data and methods into a single entity is called encapsulation. Encapsulation allows you to create modular units that can be reused in multiple programs. This idea of code reuse was the main motivation in the creation of the OOP paradigm. Another beneficial consequence of encapsulation is information hiding. The data inside the object is shielded from the outside world so that unwanted changes to the data cannot occur. Instead of accessing a variable directly, the object has a public interface that the external program should use to access and change data members. By using an interface, you can control how the object behaves and ensure that its operation is consistent across many programs. The interface also allows you to make internal changes to the code, without changing the way the object is accessed. As long as you don’t change the published interface, that is change any existing public methods, you can improve the object without breaking any existing code that relies on the object. In the cases where a program my need an improved method, you can leave the old method in place to maintain compatibility, and just add a new method with the improved functionality. New programs can use the new method, while old programs can still use the old method. Another advantage of using a public interface is so that other programmers can use your object without worrying about the internal details of the object. As long as the published interface is stable and well documented, anyone should be able to use your object, even beginners. THE PUBLISHED CONTRACT:As already stated, OOP was designed to enable code reuse among programmers. In order for code reuse to be helpful, the published interface must remain stable. That is, once an object has been released and is being used in programs, the published interface should not change so that programs that use the object continue to work correctly. There is an implicit contract between you as the author of the object and the end-user of your object that you will maintain the published interface across changes that may need to be made to the object. This implicit contract between author and user is the main strength of the OOP paradigm, and is the main reason that OOP has become such a powerful programming methodology. THE CHARACTERISTICS OF AN OBJECT:As already mentioned, an object contains both data and methods. The data describes the properties of an object, while the methods describe what the object can do. A simple, and not-really-useful example will illustrate this concept. Suppose you want to create an object that draws a rectangle on the screen. A rectangle can have several properties that would be contained within the data members of the object. A rectangle has an origin on the screen, normally the top left corner, which can be represented by x and y data members. A rectangle has a width and a height, so the object would have width and height data members. A rectangle can either be outlined or filled, so a filled flag data member can be added to the object. Of course, if you are going to draw a rectangle, you will want to draw it in a particular color, so the object will need to have a color data member, and to have the object be a bit more flexible, you can add a color member for the outline and a different color member for the fill. Of course you will need a method to actually draw the rectangle on the screen, so you can add a draw routine to the object definition. So our rectangle object has the following preliminary properties and methods:
A RECTANGLE TYPE DEFINITION:The following code snippet is a partial rectangle definition: Type myRect Private: X As Integer Y As Integer Width As Integer Height As Integer Filled As Integer Otlncolor As Integer Fillcolor As Integer Public: Declare Sub DrawRect() End Type As you can see, the extended Type looks much like a standard Type except for the Private: and Public: keywords and the sub declaration. The Private: keyword tells the compiler that the data members that follow are private to the type, that is cannot be accessed outside of the type. The private state extends to all object members until a new qualifier is encountered, which in this case is the Public: qualifier just above the Sub declaration. All of the data members are hidden from the outside world and cannot be changed from outside the scope of the Type, a process called information hiding. Information hiding is a way to maintain the integrity of the object. You should never allow an outside process to directly access a data member. All data access should be through the use of Property members so that you can control what is being passed to your object. Strict control over your object’s data will help prevent many errors that may occur when a programmer uses your object. Type myRect Private: X As Integer Y As Integer Width As Integer Height As Integer Filled As Integer Otlncolor As Integer Fillcolor As Integer Public: Declare Sub DrawRect() Declare Property SetX(Byval xx As Integer) Declare Property GetX() As Integer Declare Property SetY(Byval yy As Integer) Declare Property GetY() As Integer Declare Property SetWidth(Byval w As Integer) Declare Property GetWidth() As Integer Declare Property SetHeight(Byval h As Integer) Declare Property GetHeight() As Integer Declare Property SetFilled(Byval f As Integer) Declare Property GetFilled() As Integer Declare Property SetOtlncolor(Byval oc As Integer) Declare Property GetOtlncolor() As Integer Declare Property SetFillColor(Byval fc As Integer) Declare Property GetFillColor() As Integer End Type The Declare statements following the Public: qualifier comprises the public interface to your object. Since the variables of the type are defined with the Private: keyword, the only way to access the variables is through the Property members. Each variable has a corresponding Set* and Get* property that sets and returns the variable values. While this may seem to be a lot of code for such a simple object, Property members protects the integrity of the object. Since you define the code in each Property member, you have full control over what is being put into your object. If you allowed unrestricted access to your data members, you would lose that control, and lose the integrity of the object. In this example, the variables can be both written and read. To create a write-only variable you would add just a Set property. To add a read-only variable, you would just create a Get property. The names of the Property members are not reserved; you can name them anything you want, but using Get and Set or Write and Read in the Property name will document what the property does. CREATINF WELL-BEHAVED OBJECTS:The definition looks complete at this point, but there is a problem. What would happen if some or all of the variables were not initialized? The object would not perform correctly and potentially generate a runtime error. It would be better to have a set of default values for the object variables just in case one or more variables did not get initialized. You can initialize the object at the moment of creation by using a Constructor. A Constructor is a subroutine that is called when the object is created using the Dim (or New) statement. Constructors are useful for initializing an object, either with default values, or values you pass to the Constructor. The updated type definition now looks like the following: Type myRect Private: X As Integer Y As Integer Width As Integer Height As Integer Filled As Integer Otlncolor As Integer Fillcolor As Integer Public: Declare Sub DrawRect() Declare Property SetX(Byval xx As Integer) Declare Property GetX() As Integer Declare Property SetY(Byval yy As Integer) Declare Property GetY() As Integer Declare Property SetWidth(Byval w As Integer) Declare Property GetWidth() As Integer Declare Property SetHeight(Byval h As Integer) Declare Property GetHeight() As Integer Declare Property SetFilled(Byval f As Integer) Declare Property GetFilled() As Integer Declare Property SetOtlncolor(Byval oc As Integer) Declare Property GetOtlncolor() As Integer Declare Property SetFillColor(Byval fc As Integer) Declare Property GetFillColor() As Integer Declare Constructor() Declare Constructor(xx As Integer, yy As Integer, w As Integer, _ h As Integer, f As Integer, oc As Integer, _ fc As Integer) End Type You will notice in the definition that we have two Constructors, one that takes a set of parameters and one that doesn’t. This is called overloading and can be used not only with Constructors but also with other subroutines and functions. Overloading is useful for situations where you need to handle different parameter types with a single method call. The compiler will determine which method to call based on the parameters passed to the method. You can overload as many methods as you want, as long as the number and type of parameters for each method is unique. In this instance, if the Constructor is not passed any parameter values, it will initialize the variables to a set of default values. If the Constructor is called with parameters, then it will use the passed values to initialize the object’s variables. There is also a Destructor method that is called when the object is destroyed. You can use the Destructor to perform any cleanup tasks that must be carried out before the object is released from memory. If the object created any pointer references, or opened any files, then you would clean up those references in the Destructor. Since the Rectangle object doesn’t create any outside references, a Destructor is not needed. FILLING IN THE OBJECT METHODS:The type definition is a template for the object type and tells the compiler how to set up the object in memory. However, in order to actually use the object, you need to create the actual method calls, which is shown in the next listing. Type myRect Private: X As Integer Y As Integer Width As Integer Height As Integer Filled As Integer Otlncolor As Integer Fillcolor As Integer Public: Declare Sub DrawRect() Declare Property SetX(Byval xx As Integer) Declare Property GetX() As Integer Declare Property SetY(Byval yy As Integer) Declare Property GetY() As Integer Declare Property SetWidth(Byval w As Integer) Declare Property GetWidth() As Integer Declare Property SetHeight(Byval h As Integer) Declare Property GetHeight() As Integer Declare Property SetFilled(Byval f As Integer) Declare Property GetFilled() As Integer Declare Property SetOtlncolor(Byval oc As Integer) Declare Property GetOtlncolor() As Integer Declare Property SetFillColor(Byval fc As Integer) Declare Property GetFillColor() As Integer Declare Constructor() Declare Constructor(xx As Integer, yy As Integer, w As Integer, _ h As Integer, f As Integer, oc As Integer, _ fc As Integer) End Type Sub myRect.DrawRect() Line (x, y)-(x + Width - 1, y + height - 1), Otlncolor If Filled <> 0 Then Paint (x + 1, y + 1), Fillcolor, Otlncolor End If End Sub Property myRect.Setx(Byval xx As Integer) x = xx End Property Property myRect.Getx() As Integer Return x End Property Property myRect.Sety(Byval yy As Integer) y = yy End Property Property myRect.Gety() As Integer Return y End Property Property myRect.SetWidth(Byval w As Integer) Width = w End Property Property myRect.GetWidth() As Integer Return Width End Property Property myRect.SetHeight(Byval h As Integer) Height = h End Property Property myRect.GetHeight() As Integer Return Height End Property Property myRect.SetFilled(Byval f As Integer) Filled = f End Property Property myRect.GetFilled() As Integer Return Filled End Property Property myRect.SetOtlncolor(Byval oc As Integer) Otlncolor = oc End Property Property myRect.GetOtlncolor() As Integer Return Otlncolor End Property Property myRect.SetFillColor(Byval fc As Integer) Fillcolor = fc End Property Property myRect.GetFillColor() As Integer Return Fillcolor End Property Constructor myRect X = 0 Y = 0 Width = 10 Height = 10 Filled = 0 Otlncolor = 15 Fillcolor = 7 End Constructor Constructor MyRect (xx As Integer, yy As Integer, w As Integer, _ h As Integer, f As Integer, oc As Integer, _ fc As Integer) X = xx Y = yy Width = w Height = h Filled = f Otlncolor = oc Fillcolor = fc End Constructor The Methods and Properties are defined using the Sub/Function/Property methodname.TypeName syntax. This tells the compiler how to match up methods with the proper type definition. The Constructors are defined with the type name for the same reason. USING YOUR OBJECT:The object is now complete can be used in a program which is listed below. Type myRect Private: X As Integer Y As Integer Width As Integer Height As Integer Filled As Integer Otlncolor As Integer Fillcolor As Integer Public: Declare Sub DrawRect() Declare Property SetX(Byval xx As Integer) Declare Property GetX() As Integer Declare Property SetY(Byval yy As Integer) Declare Property GetY() As Integer Declare Property SetWidth(Byval w As Integer) Declare Property GetWidth() As Integer Declare Property SetHeight(Byval h As Integer) Declare Property GetHeight() As Integer Declare Property SetFilled(Byval f As Integer) Declare Property GetFilled() As Integer Declare Property SetOtlncolor(Byval oc As Integer) Declare Property GetOtlncolor() As Integer Declare Property SetFillColor(Byval fc As Integer) Declare Property GetFillColor() As Integer Declare Constructor() Declare Constructor(xx As Integer, yy As Integer, w As Integer, _ h As Integer, f As Integer, oc As Integer, _ fc As Integer) End Type Sub myRect.DrawRect() Line (x, y) - (x + Width, y + height), Otlncolor, B If Filled <> 0 Then Paint (x + 1, y + 1), Fillcolor, Otlncolor End If End Sub Property myRect.Setx(Byval xx As Integer) x = xx End Property Property myRect.Getx() As Integer Return x End Property Property myRect.Sety(Byval yy As Integer) y = yy End Property Property myRect.Gety() As Integer Return y End Property Property myRect.SetWidth(Byval w As Integer) Width = w End Property Property myRect.GetWidth() As Integer Return Width End Property Property myRect.SetHeight(Byval h As Integer) Height = h End Property Property myRect.GetHeight() As Integer Return Height End Property Property myRect.SetFilled(Byval f As Integer) Filled = f End Property Property myRect.GetFilled() As Integer Return Filled End Property Property myRect.SetOtlncolor(Byval oc As Integer) Otlncolor = oc End Property Property myRect.GetOtlncolor() As Integer Return Otlncolor End Property Property myRect.SetFillColor(Byval fc As Integer) Fillcolor = fc End Property Property myRect.GetFillColor() As Integer Return Fillcolor End Property Constructor myRect() X = 10 Y = 10 Width = 100 Height = 100 Filled = 0 Otlncolor = 14 Fillcolor = 0 End Constructor Constructor MyRect (xx As Integer, yy As Integer, w As Integer, _ h As Integer, f As Integer, oc As Integer, _ fc As Integer) X = xx Y = yy Width = w Height = h Filled = f Otlncolor = oc Fillcolor = fc End Constructor 'Create a graphic screen Screen 18 'Create an object using the default constrcutor Dim aRect As myRect 'Create an object by explicitly setting the constructor values Dim bRect As myRect = myRect(200, 200, 200, 100, 1, 15, 9) 'Draw the rectangles on the screen aRect.DrawRect bRect.DrawRect 'Update aRect properties aRect.SetX = 90 aRect.SetY = 20 aRect.SetFilled = 1 aRect.SetFillColor = 15 'Draw new rect aRect.DrawRect Sleep End To initialize the object using the default Constructor, you simply Dim the extended Type just as you would the standard type. If the Constructor only takes a single value then you can use the Dim var as Typename = value syntax. To initialize the object with a set of values, you Dim the type and then use the = typename(par1m parm1…) syntax. You can see that accessing the members of the object is just like accessing the member of a standard type. In this tutorial, you saw how to define, create and use the new OOP features of the extended Type. Objects are a great way to create reusable code units, and provide a way to make your programs easier to manage and much less prone to errors. When FreeBasic has Classes, you will be able to transfer this knowledge to the Class object and be able to add even more functionality to your programs. |
||||||||||||||||||||||
Simulating Polymorphic Methods Using FreeBasic Extended Types: by Rick D. Clark |
||||||||||||||||||||||
Introduction:Polymorphism is a powerful tool in object-oriented program. A polymorphic method (Sub or Function) behaves differently depending on the definition of the object. For example, an animal object may have a speak method that will issue a bark for a dog and a meow for a cat. FreeBasic doesn’t yet support true polymorphism; this will be added when classes are implemented. However, you can simulate polymorphic methods using method pointers. Getting StartedIn order to use the new type constructs, you will need to download the CVS version of the compiler; Windows, Linux or DOS.. You select the large version if you are updating for the first time. If you have not done so, download and install the last stable .17 release that you will find on the FreeBasic download page. Once .17 is installed, then unpack the CVS version in the same install folder, overwriting all files. PolymorphismPolymorphic methods are subroutines or functions that have the same type and parameter list, but behave differently when bound to different objects. An animal object may have a Speak method that will issue a bark for a dog and a meow for a cat. Since FreeBasic doesn’t yet have classes, you cannot implement true polymorphic methods, but you can simulate the behavior by using method pointers. The following listing shows a couple of defines and an extended type declaration: #define isdog 1 #define iscat 2 Type animal Public: speak As Sub() Declare Constructor (anid As Integer) End Type The #defines are passed to the Constructor to signal what type of object is being created. The speak As Sub()definition defines the method pointer. As you will see, the address of two different subroutines will be passed to the speak method pointer. The following listing shows the different speak subroutines and the Constructor method: 'Speak method for dog object Sub Bark() Print "Woof!" End Sub 'Speak method for cat object Sub Meow() Print "Meow!" End Sub 'Set the proper method pointer based on animal id Constructor animal(anid As Integer) If anid = isdog Then this.speak = @Bark Elseif anid = iscat Then this.speak = @Meow End If End Constructor The Bark subroutine will be called if the object is a dog and the Meow subroutine will be called if the object is a cat. You may be wondering why you can’t just overload the method? For overloaded methods, the type and parameter list must be unique, where in a polymorphic method, the type and parameter list must be the same. Since Bark and Meow have the same parameter list, that is no parameters, you cannot overload the method. The Constructor code is where the program decides what method call to use. If anid is equal to isdog, then the Speak method pointer will be set to the address of the Bark subroutine. If anid is equal to iscat then Speak will be set to the address of the Meow subroutine. The addressof operator @ is used to pass the address of Bark and Meow to the Speak pointer. The this object reference is a hidden parameter that is passed to the Constructor that references the type, which in this case is animal. You can use this to reference the internal variables within the type. The only thing left to do is to create and initialize the object: 'Create a dog and cat object Dim myDog As animal = isdog Dim mycat As animal = iscat Here myDog and myCat are created with the appropriate flags passed to the Constructor so that the proper references can be set up. Once the object are created you can call the speak method of each object. 'Have the animals speak Print "My dog says "; myDog.speak() Print "My cat says "; myCat.speak() Notice that you are calling the same speak method, yet the output is different: My dog says Woof! My cat says Meow! This is the essence of polymorphic methods. By using polymorphic techniques, you can enhance the capabilities of your objects, and when classes are implemented, you will be ready to use this powerful OOP tool. Here is the complete program listing: 'Simulated Polymorphism Using Method Pointers 'Richard D. Clark 'Requires the CVS version of FreeBasic '********************************************** #define isdog 1 #define iscat 2 Type animal Public: speak As Sub() Declare Constructor (anid As Integer) End Type 'Speak method for dog object Sub Bark() Print "Woof!" End Sub 'Speak mehod for cat object Sub Meow() Print "Meow!" End Sub 'Set the proper method pointer based on animal id Constructor animal(anid As Integer) If anid = isdog Then this.speak = @Bark Elseif anid = iscat Then this.speak = @Meow End If End Constructor 'Create a dog and cat object Dim myDog As animal = isdog Dim mycat As animal = iscat 'Have the animals speak Print "My dog says "; myDog.speak() Print "My cat says "; myCat.speak() Sleep End |
||||||||||||||||||||||
FreeBASIC File/Folder Management: by Stephane Richard (MystikShadows) |
||||||||||||||||||||||
INTRODUCTION:Many times when programming an application (or even games) you find yourself coming across the subject of creating files folders (or deleting them) for more than one reason. Luckily FreeBASIC has everything we need to help us with all of these functionalities. In this tutorial I'll cover all of the file/folder oriented statements and functions that exist in freebasic and well see hwo and when they can be used in order to bring some good standard file and folder management functionality to your programming projects. So let's start off with a little reference of the commands we'll be using and take it from there. FREEBASIC FILE AND FOLDER COMMANDS AND FUNCTIONS:There are several commands and functions available to create, delete, maganage files and folders.
And now that we have the reference material we need let's see what we can do with them. We will take each one and see how to use them in given situations and perhaps implement some safegards in code to help minimize errors that could occur. For this we will create our own little COMMAND.COM so to speak. A little program that will accept input from the user and perform the current actions required by the commands we'll enter in the system. BUILDING OUR OWN COMMAND PROCESSOR:As a first note, I'd like to point out that this will be a very simplistic command processor. it's purpose is to highlight the freebasic commands and functions for file/folder manipulation, so it will essetially be a simple loop with string manipulation to decipher the commands entered. But it will be something functional that can later be altered to perform as expected. It will not allow to execute other files for examples, just internal commands for the purpose of this tutorial. The sample program created here can be acquired from this link so you don't have to type or edit anything. First off we'll create the core processor/command acquisition system and we'll add commands to it as we progress in this tutorial. The framework itself shown here has functions to get parts of the entered command, this is how we'll know which command has been entered and what to do with them. ' ------------------------------------- ' BASIC command processor application ' by MystikShadows ' ------------------------------------- #INCLUDE "dir.bi" ' ------------------------------- ' Sub and Function Declarations ' ------------------------------- DECLARE SUB PrintApplicationInformation() DECLARE SUB DisplayHelpScreen() DECLARE SUB ProcessCommand(ToBeProcessed AS STRING) DECLARE FUNCTION GetWordCount(WorkString AS STRING) AS INTEGER DECLARE FUNCTION GetWordNumber(WorkString AS STRING, WordNumber AS LONG) AS STRING ' ----------------------------- ' Needed Constant Definitions ' ----------------------------- CONST False = 0 CONST TRue = NOT False CONST HeaderColor = 15 ' White CONST InfoColor = 11 ' Light Cyan CONST CommandColor = 14 ' Yellow CONST ErrorColor = 12 ' Light Red CONST ResultColor = 10 ' Light Green ' ------------------------- ' Needed Global Variables ' ------------------------- DIM SHARED CurrentCommand AS STRING DIM SHARED CanExit AS INTEGER ' ------------------------------------------------------ ' Start by displaying the title and general informaion ' ------------------------------------------------------ WIDTH 80, 50 COLOR 7, 1 CLS CALL PrintApplicationInformation() ' ----------------------------------------------------- ' Main loop where commands are acquired and processed ' ----------------------------------------------------- DO WHILE CanExit = False ' --------------------------- ' Get command from the user ' --------------------------- COLOR CommandColor, 1 PRINT "->"; INPUT CurrentCommand CALL ProcessCommand(CurrentCommand) ' ------------------------------------------- ' We Clear the command, ready for a new one ' ------------------------------------------- CurrentCommand = "" LOOP ' ======================================================== ' NAME........: PrintApplicationInformation() ' PARAMETERS..: None ' RETURN......: No value ' ASSUMES.....: Nothing ' CALLED FROM.: Main Program Loop ' -------------------------------------------------------- ' DESCRIPTION.: This Sub simply displays some regular ' information to the user about this ' current program ' ======================================================== SUB PrintApplicationInformation() COLOR HeaderColor, 1 PRINT "MystikShadow's Command Processor Application" PRINT "Version 1.00a" PRINT COLOR InfoColor, 1 PRINT "Type 'HELP' for a list of commands" PRINT "Type 'EXIT' to end the program" PRINT END SUB ' ======================================================== ' NAME........: DisplayHelpScreen() ' PARAMETERS..: None ' RETURN......: No Value ' ASSUMES.....: Nothing ' CALLED FROM.: The Main Program Loop ' -------------------------------------------------------- ' DESCRIPTION.: This Sub displays a list of valid ' commands available to the user. So that ' he/she can learn the allowed commands. ' ======================================================== SUB DisplayHelpScreen() COLOR ResultColor, 1 PRINT "Valid Commands Are:" PRINT PRINT "TIME Returns The Current Time" PRINT "DATE Returns The Current Date" PRINT "CD [ What this code so far is wait for the user to enter a command in the system. once entered, the ProcessCommand() subroutine is called. As you can see from the code to ProcessCommand() subroutine so far we manage two commands HELP and QUIT. The last two functions you see in the code are the string manipulation function we'll need to get the different parts of the command entered by the user. If you compile the program like it is now, run it and enter the help command. Here's what you will see on the screen: After that, just enter EXIT to leave the program. The command list you see on the screenshot are the commands we will be implementing in this tutorial. Four of the commands (CLS, TIME, DATE and CD without parameters are very easy to code for so in the ProcessCommand we'll just add CASE statements for each of them. Here's what the ProcessCommand() subroutine should look like: SUB ProcessCommand(ToBeProcessed AS STRING) ' ------------------------------- ' We take care of easy commands ' ------------------------------- COLOR ResultColor, 1 SELECT CASE TRIM$(UCASE$(ToBeProcessed)) CASE "TIME" PRINT TIME$ PRINT EXIT SUB CASE "DATE" PRINT DATE$ PRINT EXIT SUB CASE "CLS" COLOR 7, 1 CLS EXIT SUB CASE "CD" PRINT CURDIR$ PRINT EXIT SUB CASE "HELP" CALL DisplayHelpScreen() EXIT SUB CASE "EXIT" CLS END END SELECT In the case of these commands, as you can see, what goes on is very straightforward. Simple code is executed in each of these cases. now we need to add validation and tell the user if they entered a command that isn't recognized. Since we already have the list of valid command it will be rather easy to know if the command entered is valid or not. So We'll add, at the beginning of the subroutine, a condition to ProcessCommand() to validate the command like so: SUB ProcessCommand(ToBeProcessed AS STRING) DIM FirstWord AS STRING ' ------------------------------------------------- ' First we test of the command is a valid command ' ------------------------------------------------- FirstWord = TRIM$(UCASE$(GetWordNumber(ToBeProcessed, 1))) IF FirstWord <> "TIME" AND FirstWord <> "DATE" AND _ FirstWord <> "CLS" AND FirstWord <> "CD" AND _ FirstWord <> "CD.." AND FirstWord <> "CD\" AND _ FirstWord <> "DIR" AND FirstWord <> "REN" AND _ FirstWord <> "RENAME" AND FirstWord <> "DEL" AND _ FirstWord <> "DELETE" AND FirstWord <> "MD" AND _ FirstWord <> "RD" AND FirstWord <> "HELP" AND _ FirstWord <> "EXIT" THEN COLOR ErrorColor, 1 PRINT "An Invalid Command Was Entered" PRINT EXIT SUB END IF ' ------------------------------------ ' Next we take care of easy commands ' ------------------------------------ COLOR ResultColor, 1 SELECT CASE TRIM$(UCASE$(ToBeProcessed)) CASE "TIME" PRINT TIME$ PRINT EXIT SUB CASE "DATE" PRINT DATE$ PRINT EXIT SUB CASE "CLS" COLOR 7, 1 CLS EXIT SUB CASE "CD" PRINT CURDIR$ PRINT EXIT SUB CASE "HELP" CALL DisplayHelpScreen() EXIT SUB CASE "EXIT" CLS END END SELECT END FUNCTION Note that I added "CD.." and "CD\" as valid commands because typical DOS users didn't put spaces for these two commands (just a hint of user consideration). Basically, if the command entered isn't one that appears in the if statement we will warn the user that an invalid command has been entered. ADDING COMMANDS TO THE COMMAND PROCESSOR:Now that we validate our commands it's time to get to the real part of the tutorial. This is were we start to really look at what the user wants to do. To do so, we'll need a few other variables in our ProcessCommand() subroutine. We will put them at the beginning of the subroutine after the first DIM statement already there. DIM SecondWord AS STRING DIM ThirdWord AS STRING DIM WorkFile AS STRING DIM WordCounter AS INTEGER DIM FolderCounter AS INTEGER DIM FileCounter AS INTEGER These variables will come in handly to implement the rest of the supported commands. As you can see from the screenshot SecondWord and ThirdWord are there get the 2nd and 3rd part of the statement (since 2 parameters will be the most we need to deal with we only need SecondWord and ThirdWord). First we'll Implement the CD family of commands. After the SELECT CASE that's already there, we will first add statements to get the second and third word if we need to in order to complete the statements entered by the user. Here is the code to add at the end of the ProcessCommand() subroutine: ' --------------------------------------------- ' We get the rest of the words in the command ' --------------------------------------------- WordConter = GetWordCount(ToBeProcessed) IF WordCounter = 2 THEN SecondWord = GetWordNumber(ToBeProcessed, 2) ELSEIF WordCounter = 3 THEN SecondWord = GetWordNumber(ToBeProcessed, 2) ThirdWord = GetWordNumber(ToBeProcessed, 3) END IF Now the first command we will implement is the CD command. Remember that CD by itself simply displays the current directory to the user and is already coded for. This part will take care of the other forms of CD commands. Typically the user will enter CD followed by a folder name, a .. or a \. Like I mentionned earlier DOS users don't usually enter spaces for .. and \ so we will add direect support for CD.. and CD\ without spaces. Here's the code to the CD command: ' ------------------------------------------------------------------------- ' This SELECT CASE decides which code to executed for the command entered ' ------------------------------------------------------------------------- SELECT CASE FirstWord ' ------------------------------- ' THE CD command implementation ' ------------------------------- CASE "CD", "CD..", "CD\" ' ----------------------------------------- ' Test for the existence of the directory ' ----------------------------------------- IF DIR$(SecondWord, fbDirectory) = "" AND SecondWord <> "\" THEN ' ------------------------------------------------------- ' If the directory does not exist, we display a message ' ------------------------------------------------------- COLOR ErrorColor, 1 PRINT "This Directory does not exist. Path remains unchanged." PRINT CURDIR$ PRINT COLOR ResultColor ELSE ' ------------------------------------------------ ' Test to see if none spaced .. andn \ were used ' Execute appropriate command in these cases. ' ------------------------------------------------ IF FirstWord = "CD.." THEN CHDIR ".." ELSEIF FirstWord = "CD\" THEN CHDIR "\" ' --------------------------------------------------- ' In all other cases we just CHDIR to the directory ' --------------------------------------------------- ELSE ' ----------------------------------------------- ' If it does exist we CHDIR right to the folder ' ----------------------------------------------- CHDIR SecondWord END IF PRINT CURDIR$ END IF PRINT EXIT SUB END SELECT You can note that we also added a test to see if the folder the user wants to change to actually exists. We warn them if it doesn't exist and nothing else happens. If the directory does exist, We use CHDIR to change to the specified directory. Using this code the user can enter any valid CHDIR statements after the CD command and it will perform as expected. The next command on our list is the MD command. This command is a bit simpler to code for than the CD command because it doesn't have any variants to it. The user would simply type MD FolderName to create the desired folder. We will simply test to see if the folder they are trying to create already exists and warn them if it does. Here's the code for the MD command. It is added to the SELECT CASE statement we just created previously. ' ------------------------------- ' The MD Command Implementation ' ------------------------------- CASE "MD" ' ------------------------------------- ' We test to see if the folder exists ' ------------------------------------- IF DIR$(SecondWord, fbDirectory) <> "" THEN ' ------------------------------------ ' If it does exist, we warn the user ' ------------------------------------ COLOR ErrorColor, 1 PRINT "This Directory already exists, unable to create it." PRINT COLOR ResultColor, 1 ELSE ' ------------------------------------------------------- ' If it doesn't exist, we simply go ahead and create it ' ------------------------------------------------------- MKDIR SecondWord END IF EXIT SUB As you can see, the code is straight forward and rather clear we either create the folder or we don't (if the folder already exist). This is the only test we really need to do. Up next on our list is the RD command which removes a directory from the disk. Remember that RD will not work if the directory to be removed already has files in it. Coding for the RD command should be quite similar to the MD command with the added test to see if there are files in the folder we want to remove. If there are, we'll warn the user that they are files. If no files exist in the directory we'll go ahead and use RMDIR to remove the folder. ' ------------------------------- ' The RD Command Implementation ' ------------------------------- CASE "RD" ' ------------------------------------ ' First we test if the folder exists ' ------------------------------------ IF DIR$(SecondWord, fbDirectory) = "" THEN COLOR ErrorColor, 1 PRINT "This Directory does not exist hence cannot be removed." PRINT COLOR ResultColor, 1 ' -------------------------------------------------- ' Next we test if there are files in the directory ' -------------------------------------------------- ELSEIF DIR$(CURDIR$ + "\" + SecondWord + "\*.*") <> "" THEN COLOR ErrorColor, 1 PRINT "The Directory has files in it and cannot be removed." PRINT COLOR ResultColor, 1 ' ----------------------------------------------------- ' If all is good we go ahead and remove the directory ' ----------------------------------------------------- ELSE RMDIR SecondWord END IF EXIT SUB Simply put we do two consecutive tests, the first to see if the folder exists in the first place, if it does, we're good we can go to the second test which is to test if the directory has any files in it. If there are files we warn the user since the directory won't be removed. if there are no files we go ahead and remove the directory. The next command on the list is the DIR command. The DIR command lists files that match the specified File masks. Shortcuts can be used here such as the standard "*.*" and the "?" to filter out unwanted files. In this version I am doing two things when a DIR command is issued. I first list the folders (if any) that match the file mask and then I list the files that match the file mask. I will also accumlate the results to tell the user how many folders and files were found for the DIR command they issued. I added a little feature which if DIR is called without a file mask I default it to *.* instead of warning them of an invalid command. here's the code to the DIR command CASE STATEMENT (again to be added at the end of the SELECT CASE STATEMENT): ' -------------------------------- ' The DIR Command Implementation ' -------------------------------- CASE "DIR" FolderCounter = 0 FileCounter = 0 ' ---------------------------------------------------- ' We first list the folders in the current directory ' ---------------------------------------------------- IF SecondWord = "" THEN WorkFile = DIR$("*", fbDirectory) ELSE WorkFile = DIR$(SecondWord, fbDirectory) END IF DO WHILE TRIM$(WorkFile) <> "" IF LEFT$(WorkFile, 1) <> "." THEN FolderCounter = FolderCounter + 1 PRINT WorkFile & "\" END IF WorkFile = DIR$() LOOP ' ------------------------------------------------- ' We then list the files in the current directory ' ------------------------------------------------- IF SecondWord = "" THEN WorkFile = DIR$("*") ELSE WorkFile = DIR$(SecondWord) END IF DO WHILE TRIM$(WorkFile) <> "" FileCounter = FileCounter + 1 PRINT WorkFile WorkFile = DIR$() LOOP ' -------------------------------------------------------------- ' We finally display the folder and file counts we accumilated ' -------------------------------------------------------------- PRINT PRINT "There were " + STR$(FolderCounter) + _ " directories and " + STR$(FileCounter) + _ " files listed." PRINT EXIT SUB Basically, this code is created to show you examples (hopefully realword examples) on how to use these commands, the things to watch out for when using them and the likes. This is why I do things like check for the existence of a folder before I try to CHDIR to it or something. Nothing happens if there's no files to list. If there are files then they will be listed one after the other as long as the search yields a file. Quite straight forward. And now we have the DEL and DELETE commands. Like DOS you can used both DEL or DELETE (whatever you are used to) to delete files on your disk. The only test we need to do here is to see if the file they want to delete actually exists, if so, then we use the KILL statement to delete the file. If it does not exist we'll simply warn the user about it and do nothing else. here's the CASE statement for the DEL, DELETE command (you guessed it, at the end of the SELECT CASE statement is where it goes): ' ------------------------------------------- ' The DEL and DELETE Command Implementation ' ------------------------------------------- CASE "DEL", "DELETE" ' --------------------------------- ' First we see if the file exists ' --------------------------------- IF DIR$(SecondWord) = "" THEN COLOR ErrorColor, 1 PRINT "This file does not exist, unable to delete it." PRINT COLOR ResultColor, 1 ' ---------------------------------------------------------- ' If the file exists we go ahead and use KILL to delete it ' ---------------------------------------------------------- ELSE KILL SecondWord END IF EXIT SUB Very simple test that basically says that if the file exists we can delete it, if it does not exist we just let the user know (in which case he will just repeat the command with the right file name the next time around, hopefully). Pretty simple isn't it? I thought so. And we are at the final command to be implemented, the REN and RENAME commands. This is the only command that needs all three parameters, hence we'll have to do some validation on them to make sure everything is good to perform the renaming of the file in question. First test will be the old file name is not empty. If it is empty we let the user know and we do nothing else (EXIT SUB). The next test is to see that the new file name is not empty. if it is empty, once again, we warn the user and exit the subroutine. If it is not empty we go to the third test which is to see that the old file name actually exists on the current or specified folder. If we're still good after these 3 tests we go ahead and use the NAME statement to rename the old file name (SecondWord) to the new file name (ThirdWord). Here is the last CASE STATEMENT to be added to our codebase: ' ------------------------------------------- ' The REN and RENAME Command Implementation ' ------------------------------------------- CASE "REN", "RENAME" ' ---------------------------------------------- ' First we test that Old Filename Is not empty ' ---------------------------------------------- IF SecondWord = "" THEN COLOR ErrorColor, 1 PRINT "The name of an existing file is needed to rename the file." PRINT COLOR ResultColor, 1 EXIT SUB ' --------------------------------------------- ' Next we test that New Filename Is not empty ' --------------------------------------------- ELSEIF ThirdWord = "" THEN COLOR ErrorColor, 1 PRINT "A new name is needed to rename the file." PRINT COLOR ResultColor, 1 EXIT SUB ' ---------------------------------------------- ' Finally we test that the old filename exists ' ---------------------------------------------- ELSEIF DIR$(SecondWord) = "" THEN COLOR ErrorColor, 1 PRINT "The file you are trying to rename does not exist." PRINT COLOR ResultColor, 1 EXIT SUB ' -------------------------------------------------------------- ' If all went well we go ahead and use NAME to rename the file ' -------------------------------------------------------------- ELSE NAME SecondWord, ThirdWord EXIT SUB END IF As you can see, it's really all about implementing some basic tests before performing the actual command just to be sure everything is good, ready and safe to perform the actual command. With these in place the command processor becomes a bit more stable a tool to use for the user and for the user's files and folders of course. A FEW NOTES: Now remember this sample program is mean to illustrate the use of the file and folder commands provided by FreeBASIC. Hence the emphasis is on those commands. Of course I could have used another method than input to get the user's commands. I could have done things a bit different (like perhaps add some good Drive, Path and file name validation for example) but the important part is what I do with the file and folder commands themselves. IN CONCLUSIONAnd there you have it, I believe we've covered all of the commands offered by FreeBASIC as far as files and folder management goes. Of course FreeBASIC has more commands (like CHAIN, EXEC, RUN and SHELL) that have the potential to add more functionality to a program such as this command processor sample. This sample is designed to respond to user commands but any of these commands could be coded in a subroutine and called for any purpose from any type of program really. The choice is yours. As always, I hope this tutorial helped you in some way or
another. I hope it was clear but readers tend to read things
differently. So, if any of this isn't clear in your head, be sure to email me
to let me know what parts is not clear or whatever other comments or
questions you may have about this tutorial. Until next, happy coding
(and command processing). |
||||||||||||||||||||||
Exit Issue: by Stephane Richard (MystikShadows) |
||||||||||||||||||||||
And there you have, a 4th release of the magazine, you've reached the final part of the magazine. Parting is such sweet sorrow isn't it? We hope you liked this release of PCOPY! particularly because of it's contents of course but also because of it's new look and feel. So far, among the editors of the magazine we think that this is a much better color scheme and layout and we hope you agree. be sure to let us know what you think of this new layout we've created for you. We're also completely opened to suggestions. If there's something you would like to see appear in PCOPY! if it's basic related chances are it can and will be included. So don't be affraid to tell us all about it and if it's worth being in PCOPY! you can bet that it will be included as soon as possible. Don't forget to be on the lookout for the next release of PCOPY! where we'll do our very best to bring you news and other related contents about any and all BASIC dialects out there. There's a big list, going through each of these languages to get the news is a great task but I believe we're taking up this challenge head on to get you the good stuff. We hope you liked it and will continue to like in the future. Until our next edition, this is PCOPY! signing off. |