QB Express

Issue #7  ~  February 20, 2005

"A magazine by the QB community, for the QB community!"

In This Issue



From The Editor's Desk

Written by Pete

"The QB scene is so boring now! you can smell the rot."

A few weeks ago, Mechman posted that on the QB45.com message forum. And honestly, when I read it at first, I was inclined to agree with him. On the QB side of things these days, there's next to nothing happening. QB is dying a slow death, and has been for years...and the QB scene has been just pathetic for about two years now.

But then again, there's a whole lot more to the QB scene than just QB. You see, there's this little thing called FreeBasic. And it's turning the Qmunity upside down. For the first time in years, "QB" people are really excited about programming again. I haven't seen the QB community this productive since the year 2000. I don't think in his wildest dreams did V1ctor think that FreeBasic would be as popular and successful as it has become.

And then there's QB Express. In just four issues, this magazine has gone from a dedicated QBasic / QuickBasic programming magazine to a predominantly FreeBasic zine. This month, we have a FB review, two games featured in the Gallery that are both written in FreeBasic, five tutorials specifically for FreeBasic (and several that apply to both FB and QB), a News Briefs section filled to the brim with FB news, and an article entitled "FreeBasic is our future. OUR FUTURE." I think it's pretty clear that the QB community has evolved right in front of us. And this magazine has gone along for the ride.

But that's what I always intended when I started this publication last August. The tagline of this mag is "A magazine by the QB community, for the QB community!" Nowhere does it say that it is a QBasic or QuickBasic magazine... it's a QB community mag. And the QB community wants FreeBasic. Honestly, it doesn't matter what language were coding in, we're still the QB community. It's the sense of community that keep us posting on message forums, visiting sites and helping each other out. QB may be a thing of the past, but the QB community is not.

So am I going to change the name of this magazine to "FB Express"? No. I'm going to keep it as "QB". I think it's important that we remember our QB roots. Besides, does it really matter what we call ourselves? I don't think so.

Anyway, I can safely say that this is the biggest and most useful issue of QB Express ever. I can't believe it when I say it, but there are ELEVEN different tutorials in this issue. ELEVEN. And that's not to mention all the other stuff. Everything about this issue is bigger and better than before, and it's clearly because of the invigorating influence of of FreeBasic on the Qmunity. When the QB community is active, everyone has a lot of stuff to write about and submit. And that definitely happened this month. Great job, guys!

But I'm not gonna keep you waiting any longer. Go ahead and get readin'. You're gonna probably have to come back to it a few times to read everything. This is one HUGE issue, and I want you to enjoy every last word.

Submit To QB Express

You all know the drill. This magazine can't exist without people SUBMITTING articles, editorials, tutorials, reviews, news and feedback. This is not just a solo effort by me... it's a group effort by people throughout the QB community. If you have anything to submit, or have time to write something, DO IT!

If you want to write about something, but can't think of a topic, or need inspiration, email me! I'm good at thinking of stuff to write about, and I know quite a bit about the QB community and about QB programming. If you're interested in getting your own monthly column or just want to write an article or two, by all means, do it! Anything that is submitted will be included!

I also want feedback and letters to the editor regarding this magazine. I want suggestions and critiques. What do you like? What don't you like? What could be done better? Let me know!

All submissions and feedback can be sent to pberg1@gmail.com. You can also PM me on the Pete's QB Site or QBasic News message forums. If QB Express is going to continue to be so good, YOU need to contribute!

-Pete



Letters

Letter From Lachie Dazdarian

Greeting Pete,

Like with all the previous ones, I enjoyed reading this last issue(#6) of QB Express. Especially because I was able to bring it home and read it in peace. To be honest, I think it came too soon. Don't get me wrong, I just wouldn't like you too overstress yourself for no reason. None of us in QB community would like you to burn out and get sick of editing QB Express.

Anyway, I liked the editor's desk and letters section quite a lot. It's always cool too see people expressing their love for QBasic. News section is something really great too, since not all important events in QBasic community appear on www.qbasicnews.com . I can only thank you once again for keeping track on QBasic community and warning us on all important things happening in there. That's more than useful to people like me, who are not online often. FB news section is another plus. Wonderful!

Michael Wechsler's article was very interesting too. Nice insight into your life. But I should warn you, it seems to me like your roommate has a little crush on you. Just don't be surprised if you wake up one day by a cold hand feeling your privates. :P And I don't belive you can do 100 pushups every morning. Maybe them sissy pushups, but legit ones...no. :P

I don't usually go too deep into tutorials section(lack of time and the fact I'm not a keen programmer) but I found Na_th_an's IF tutor very enjoyable to read. The fact I don't like IF games much proves even more how Na_th_an's article is great. Keep it up, Nath.

But now, I must turn to the things I didn't like. I don't like doing this since I don't contribute to the magazine but I just feel I should. My only interest is to help you make the next issue better. I don't know who is Nathan1993 but his tutorial was quite badly written. To be honest, it took me several readings to get that thing. Until I realized it speaks about things I figured out myself(after learning how to use external files for storing data) ages ago. It's obviously meant for novice programmers but sadly not written on "novice-friendly" way. Simply, sloppy work. Any tutorial that has sentences like "I'm too lazy to show you this so moving on the next issue..." sucks.

Rattrapmax6 comic is really a waste of space. I'm sorry that I need to be this harsh but that comic is screaming for it. Elementary grade spelling errors, mixed up speech bubbles(character speaking to himself), utter lack of humor and ridiculous graphic. And I could pass over all the cardinal sloppiness if the comic was funny. Like this, it deserves the lowest grade. I think this comic blatantly shows Pete, how you need to install a minimum quality requirement when reviewing magazine submissions. Man, don't put everything in the magazine you get. I don't know, maybe you declined a lot of things but I can't imagine anything being worst than this comic.

Also, I liked Oz doing another game review but it was really too short and too cold. Like some sort of quick game report. Add more juice in it Oz.

This, of course, brings me to the issue of me not contributing to the magazine. I can only promise I'll try to find some free time for a game review or some sort of contemplation on LONG development. It takes me a lot of time to write something coherent. Writing is not my thing, you know. You could say I'm an anti-talent when it comes to putting thoughts into words. It all depends how good I'll do on the several upcoming exams. If I fail them, I'll feel like worthless shit(motivation drops to 0) and will have even less free time.

Anyway, that would be it. Keep up the GOOD work. ;)

Lachie Dazdarian
( www.kentauri.cjb.net - I can't update my damn site :P )

Hey Lachie, I really appreciate the criticism. It seems that normally all I get is blind praise. I'm glad there's somebody out there reading with a critical eye.

In general, I agree with you about the poor quality of some of the writing in the magazine, and I would certainly prefer if everything that we published was of consistently excellent quality. But in a volunteer magazine where I don't make any money doing this, and everything is written entirely by hobbyists, I can't always settle for Pullitzer Prize worthy material. It's very difficult to fill up this magazine, and I will take just about anything I can get. I want to make a "complete" magazine every month, meaning that there is a large quantity of varied content that will appeal to a large selection of different people. No matter how bad an article or comic or tutorial is, there is always SOMEBODY out there who will find it useful or entertaining. I don't want to cut off any reader from an article that might be helpful or entertaining to them if I can help it. And because of the medium I'm using (a webpage), there are no real practical limits to including everything I get.

Besides, when I founded this magazine, I vowed that it would be an open magazine, dedicated free speech. Anyone who wants a voice, who wants to be heard, should be able to throught his magazine. All they have to do is write something down and send it in -- and as long as it's anything that could be remotely useful to anybody, I feel that it's worthy to publish.

Anyway, I see where you're coming from, and I appreciate your thoughts. I'll definitely take them into consideration (I already have). If there's something I can do to improve the quality of the articles that are submitted in the first place, I'll do it. Maybe your criticisms will be help my writers improve, since you point out some of the poorer aspects of the content they submitted. This is a much better solution in my view than excluding the writers. Helping the writers improve is the best option for everyone.

Oh, and about Mike's article... well... I'll let you take it for what it's worth. :) Anyhow, he's back again this month with a follow-up. Check it out, I'm sure you'll like it.

-Pete

Letter From Nixon

Hey mate.

Great mag. Keep em coming. Anyway I'm replying about DOS being dead. I have found out a very interesting fact. Even though DOS seems dead it is very much still alive in businesses. I have been taking a peek at the computers I see in stores. Their programs are always in DOS. Even Harvey Norman, A massive computer store uses DOS.

I'm guessing they use it because it is stable and cheap to get. Also you don't need anything great to run it. My dad Even uses a DOS program to store customer data and phone numbers and all that.

Heres the question, is windows as good as we think it is? Is it what every business needs? My opinion is that that windows is just the flashing light that attracts people, It has alot of useless things. In truth all we really need is DOS.

One other thing I found out just a few weeks ago was that Windows makes DOS run slower. I was making a game after Windows crashed on my computer. I had a FPS counter in it and it was running about 30, 000 FPS, partly cause nothing was happening much. But when I looked at the program again once I loaded up windows and had it running, It went down to 9,000 FPS. To me I think that, that is a very large drop. My computer is only 100Mhz And I think it would do this on any other computer, but the truth is I'm not sure.

Well I guess that's all I have to say, unless I can think of something else... nope, thats all.

-Nixon

I don't disagree with you on the merits of DOS, but the reason that many businesses still operate on DOS is because their computer systems are old, and they see no reason in investing in expensive new systems when their old DOS systems still do everything they need. It's the "if it ain't broke, don't fix it" mentality. Why spend large sums of money on new computer systems when the old ones that you paid top dollar for ten or fifteen years ago still work fine? It's not that companies choose DOS over Windows or Linux or Mac OS; when they got their computers, DOS was the standard. And upgrading to a new system has other downfalls aside from the cost, such as converting a decade's worth of databaes and sales records to a new software environment. It's just not worth it.

DOS will never die completely, because it is an extremly popular legacy platform with thousands of programs written for it. But like a lot of other oudated platforms, like Commodore 64, Super Nintendo and Windows 95, no serious professional is still creating new software in it. There might be a handful of diehard hobbyists (such as us in the QB community) that still enjoy tinkering with the old platform, but there's no money to be made and no real practical use. People will still have fond memories of the old platform, and most of the time will ensure that they're still able to use the old software (through emulators or virtual machines), but it's just for nostalgia or reference.

I love DOS as much as the next guy, but face it -- the times have changed. Its technical limitations make it just too ... limited.

-Pete

Letter From Lurah

Well well well...

As usual, your last QB Express were great work. I can see that you love for making it =)

Your answer to my letter and especially this part -" then on a whim one day, I logged onto the Internet and did a search for QBasic... And here I am today."-, make me think that how many other former QBasic coders there are somewhere who haven't typed "QBasic" for search? =)

"QB's only gonna die faster if people wait to program in it or make their websites."

That's partly true (IMO). I dont see point to make new QBasic site for now. There are few real great sites at this moment so instead of making own webby now, I think it's way better if I support those web sites that exists already.

There are few others "dying" programming languages...maybe some sort of union might help QBasic? Or sites like pure-text.com? Idea of pure-text is great, let's hope that it starts to "fly" :)

Maybe there aint coming no more any real big project what puts "new limits" for QBasic coding, but im pretty sure (and hopeful) that there still keeps coming new games and programs that peoples likes to play/use.

On the other hand, one coder said to me that he thinks, QB community and present-day computers have advanced out of QBasic and its "limits".

He though that everything what can be made with QBasic have allready done. And that present-day players wants graphics and sounds what game programmer cant offer with QBasic based code.

I fear that it's true. Maybe peoples aint interest about low level graphics, or even ascii based games anymore because computers of this day offers resources for so mutch more?

I told one of my friend that im making a ascii graphics based adventure game and he was amazed, "who on earth wants to play that kind of game anymore?".

Let's hope that it was stupid and meaningles comment :)

R. lurah

P.S.: My english ain't advanced since last time =D

Käyhän piipahtamassa---> www.lemmikkini.net

There's not much we can do to make the non-programmers of the world understand the magic of QB, if they have become accustomed to modern computers with flashy new software. People who have been raised with modern computer systems have a whole lot less tolerance for the simplistic graphics and gameplay characteristic of QBasic. There's no way you're going to change that. That's the way it is.

People have become naturally conditioned to expect a minimum quality of audiovisual output from their computers, and if ASCII QB games fall below that minimum, they're not going to be impressed. I know I too have minimum expectations of what a computer can do (though they're certainly much lower than the people who dismiss QB because of its technical limitations). If I look at the very first personal computers which consisted of a few rows of light bulbs and a speaker that could emit a few different beeps, with no monitor and only a couple on/off switches for input, I would enjoy the novelty for a moment or two -- then be bored to death.

The people that enjoy QB either have nostalgia for the simplistic programs they used in the past, are interested in the novelty of ultra-simplistic, old-shool graphics and sound, or are able to see through the technical limitations and understand the creative potential of QB. I'm not surprised that your friends don't really "get" it. But hey, that's all right. To each his own, I guess. It's just a matter of preference.

-Pete

Letter From Matt2Jones

Pete,

Hey, no BBY this month but...

Here's an even more useless contribution!!!! (Editor's note: He's talking about his Music Composition Tutorial)

Well done on keeping the mag going without me though, me being the nuts and bolts that held the operation together... I forgot the punchline I had for that.

Unfortunatly I was dissapeared from the collective internet since before Christmas, because the phone lines were not connected to our house for a very long fucking time (thanks to private enterprise, bully for capitalism), so I was unable to keep up to date with QB, FB, QBExpress, all the webcomics, etc, etc.

Now when I finally got back online I was agast at the catching up I was going to have to do. Image three months worth of old forum enteries to see where everyone stands, and weeks later hearing about reveloutionary programs that came out when I was gone that I just completely missed. The anticipation of this pain was not pleasant.

Then, after finding out the Distillers Drummer quit, and the Leftover Crack Drummer died, I got the last two issues of QBXP (<- bastardised abreiviation) and now feel up to date.

Thank you Pete for making my rehabilitation so much easier.

matt2jones

Glad you like the maga! One of the main reasons I started this magazine was because I enjoyed reading the old QB magazines to find out what was happening in the Qmunity back a few years ago. I guess I'm just a sucker for QB community history. So I'm glad that this mag was able to bring you up to speed so well, now that you've returned from your two-month vacation from QB. That means that I'm at least I'm doing something right!

-Pete



Express Poll

Every issue, QB Express holds a poll to see what QBers are thinking. The poll is located on the front page of Pete's QBasic Site, so that's where you go to vote. Make sure your voice is heard!

What was your favorite part of QB Express?

SectionVotesPercentGraph
Tutorials1043%
Articles / Editorials313%
News Briefs522%
Gallery29%
Blast From the Past14%
Competition00%
Comics29%
Other00%
23 Total Votes
Not very many people participated in this poll for some reason... but as you can see, tutorials won out big, and "News Briefs" was also quite popular. I think it's interesting that "Competition" got zero votes. Whenever I have a competition, almost nobody enters -- which is consistent with the results of this poll... but when I DON'T have a competition, I always get lots of complaints. Anyhow, I guess I have a better idea now where I should focus my attention in this mag.

Let's make sure next issue's poll isn't as pathetic as this one. Go out and vote! (The poll is already up, so the fact that it's not up as you read the issue can't be an excuse.)


News Briefs

This section contains news from all around the QB/FB community, about the latest games, site updates, program releases and more!

There's seriously waaaaaaay too much news this month for me to handle, especially on the FB side of things. I'm absolutely swamped. I wasn't able to be as thorough as I usually am this month, because so much is going on. But that's a good thing. This seriously is a renaissance in the Qmunity, and it's all thanks to FreeBasic. But then again is it even the QB community anymore?

Anyhow, I've decided that I need to recruit some news reporters to help me take care of this section in the future. I'm only one man, and an extremely busy one at that -- so I don't have the time to constantly monitor all of the QB and FB sites on the Internet. So if you are interested in helping me keep track of QB or FB news, drop me an email. Basically, over the course of the month, copy and paste all the important announcements and URLs you find into a text file, and when it's time for a new issue, just write up the stories into 1-2 sentence descriptions that I can post in the mag. It's pretty easy. Trust me, I've been doing it for seven issues.

QBasic / QuickBasic News

Site News
  • NeoBasic Switches Servers, Domain Name - Marcade's popular NeoBasic site recently moved to Wildcard's server, allowing him to get rid of his Communitech server and save money. In order to move servers Marcade also had to get a new domain name. According to Marcade, "www.neozones.com is *still* under Tek's control, thus meaning I cannot update the DNS settings .. and for some reason Tek doesn't let neozones.com expire so I can take it back over. Also since he didn't response to my mails, I just decided to get another domain name." As a result, Marcade moved NeoBasic to the new domain www.neobasic.net. Everybody update your links.

    This announcement comes just a few months after Marcade shut down his Zext.Net server to save money. Zext.net was formerly a major source of free web hosting for QB sites, which have either moved elsewhere...or been taken down.

  • JacobPalm.dk Undergoes Complete Redesign and Gets QB GUI Reviews - A lot has happened in the last month at JacobPalm.dk, a relatively new QBasic site that was formerly criticized for being incompatible with FireFox web browsers. The new design is cross-browser compatible and much more pleasing to the eye. Additionally, Jacob has added over 20 QBasic GUI programs and done reviews of seventeen of them. That's no small achievement. Everybody go check out this blossoming QB site!

  • Mandelbrot Dazibao Gets New Domain - The popular graphics techniques website by Jark got its own domain last month at www.mandelbrot-dazibao.com. This site houses a treasure trove of tutorials, screenshots and example programs that explain graphical techniques like fractals and raytracing. Jark also announced "I still have this project for a Hi-Res Landscape renderer in QB..." in case you're interested.

  • V Planet's Overhaul Begins - It appears that V Planet! editor Nekrophidius has big plans for the site in the near future, because he has begun redoing the site's design and creating sections for FreeBasic Reviews, News and more. For some reason, though, Nek uploaded a work-in-progress version of the site, which is filled with broken links and is missing almost all of the huge library of useful content that former V Planet! editor Vance Velez and his staff created over the past five years. I'm not sure why he didn't finish the redesign and then upload it, but I wish the old content were still easily available.

    In other news, the 2004 QBasic Gaming Gold Awards seem to be in jeopardy. After a poor voter turnout during the preliminary nomination round, Nekrophidius seems to have either put the contest on hold or just not gotten around to moving it forward. This is unfortunate, since this is probably the last Gaming Golds ceremony that the QB world will ever see, now that FB is taking over. I know that I, for one, would like to see QB go out in a blaze of glory, instead of just being abandoned.

  • Basic Network Shutting Down? - After a period of downtime in early January, followed by a redesign which involved the loss of all the site's old content, The Basic Network has had a significant drop in user activity. So much so, in fact, that there has been nearly no activity on the site since its reopening. Nekrophidius, the site's webmaster posted a message on the Basic Network forum announcing that he may shut the site down if there isn't a significant increase in usage in the next week. Otherwise, the site could go down for good on February 25th. If you're a fan of The Basic Network, this may be your last chance to keep it alive -- so get postin'!

  • Qbasic.tk Closes and is Replaced by Freebasic.tk - Once one of the most popular forums in the QB community, QBasic.tk had been declining in usage substantially in the past few months, as most of its main users switched to FreeBasic. Seeing this trend, the folks in charge of the site felt that they should close down the QB site and replace it with a more in-demand FB site. Since Freebasic.tk opened, it has quickly become one of the most active FreeBasic communities on the Internet.

    Luckily, this important piece of QB history has not been removed permanently; all the old QBTK content has been archived and is still available. The compressed .rar archives for Qbasic.TK, which has recently been closed down, can be found here. There are 11 files, each around 5 mb, which sums up to a total around 50 mb. This contains ALL of the Qbasic.TK webcode (html, php, images, whatever), the Qbasic.TK database (all the phpbb2 posts and more), plus all the files that were uploaded to the forum (around 40mb goodies Razz).

  • New x.t.r. Graphics Site - Rattrapmax6 (Kevin) of x.t.r. Graphics has done a complete overhaul of his QBasic site. According to Kevin, he took up HTML after becoming "overly annoyed with AOL's WYSIWYG editor". The new site contains a few new features, including something called the "Links Town"... which I'll let you interpret for yourself.

  • Gordon's Freeware Site Revamped To Include 50 QB Programs - Gordon S. posted the following news at QBasic News a little while ago: "Having discovered, that amazingly there is still a very widespread interest in the dear old Qbasic in this forum, I have revamped the programs page on my site to include over 50 QB for downloading. I have included on the programs page my personal opinion on the four versions of Basic I have used. Feel free to make your comments for discussion, if you also have experience with these other Basics." You can visit Gordon's Freeware at: http://sionet.mysite.wanadoo-members.co.uk

Project News
  • New Inspiration Demo Released - A new demo of Wallace Software's First Person shooter, Inspiration was released recently. This FPS engine, which was featured in the QB Express gallery a few months back, looks phenomenal. Visit this topic for some release info. You can also take a look at Wallace Software, which is quite possibly the most updated QBasic site on the Internet these days. Wallace posts updates about his progress on Inspiration and his other projects very regularly. He is also developing some very cool effects for this engine, such as detailed dynamic lighting. Definitely worth a look.

  • Frantic Journey QB Source Code Released! - Adigun A. Polack, the head developer of the frenetic space shooter Frantic Journey, has released the QuickBasic source code of this program for a limited time. He posted the following at QBasic News on Feb. 15th: "Yep, you heard right, folks! The special Limited-Edition source code for FJ indeed is freely available to you as no less than a mighty little relic in QB gaming history, but you have *only* until the end of February 2005 to go to the Frantic Journey official pages and snag that rare sucker down!" To get this package, visit the official AAP Projects Squad site.

  • Structured Code and Bowling - There's an interesting post on writing structured QBasic code at Qbasic News, which centers around reformatting the code for a simple Bowling game. Check out this thread for details.

  • Barok's "MyRpg" Demo Released, Deceased - The engine demo of Barok's RPG engine was released recently. This project was begun in QB, but will now be finished in FB... hence the QB version now being "deceased". Check out the source code if you're interested.

  • Cool Minigame by QBN Poster's Stepson - Check out this post to try out a very fun QB minigame by a beginning programmer. I enjoyed this game quite a bit; hopefully you will too.

  • QBWIN QWshell 2004 (English version) Released - An ingenious GUI program for QB made by a chap named Hoker.bas has been making quite a stir on the QBasic News forums. This program can make very professional-looking DOS GUIs with little or no effort. Definitely worth a look!

Other News
  • QBXL Issue #4 Delayed Again, SJ Zero Goes on Exile - SJ Zero, the blunt and witty writer behind QB Accelerator Magazine has gone on an exile from the QB community as a result of poor grades in school. His leavetaking announcement came right before he was scheduled to release the new issue of QBXL which he has previously claimed is "99%" complete. However, SJ Zero has vowed that when he returns, the new issue will come and it will be something to behold: "I vow to everyone who waits for the new issue that when I finish my exile, the next qbxl will be ready, and it will be the greatest issue ever."

  • New And Never-Before-Seen QB Graphics Modes Discovered by Adigun A. Polack. Check out his announcement of his findings of new screen modes, many with 512 horizontal pixels (such as 512x350x16 color mode and 512x480x16 color mode). Interesting stuff, even if these screen modes aren't the most useful thing I've ever seen.

  • Z!re Begins QMunity Webcomic - Z!re, one of the most active members of the QB community, is at an ideal position to observe and comment on the Qmunity... Which I guess is probably the reason why he's doing just that. Z!re recently started a webcomic about the QB community, which you can find posted at FreeBasic.tk, here, or here. Currently, there are ten comics strips, and more could be right around the corner.

FreeBasic News

Site News
  • FreeBasic.tk Debuts - FreeBasic.tk debuted last month, and has become a major hub of the burgeoning FB community. But you already knew that, since I kind of mentioned it before in the QBasic.tk news story above.

  • Zap and Z!re Make FreeBasic FAQ at FreeBasic.tk - There have been many efforts to document FreeBasic, and this is the most recent. Zap and Z!re have begun a FAQ for FreeBasic programmers that could be quite useful. Check it out at this link.

  • FBIde Site Opened - FBIde developer VonGodric has created an official website for his at http://www.hot.ee/fbide. Check out the site for the latest FBIde updates, or visit some of the forum topics about FBIde.

  • FBXL: FreeBasic Extension Language - Nekrophidius has given his FB GUI Compiler a name, and begun its official site: FBXL.com. So now, instead of calling it "the GUI Compiler", we can call it "FBXL". Yay.

  • FB Tutorial Series by thegrogen - The first tutorial in a series of beginners' FB tutorials was recently created by a guy named thegrogen. He plans to create more in the future. You can find the tutorial website right here. Thegrogen said: "Also, I'm looking for freeBasic tutorial contributors, so if anyone has written a freeBasic tutorial, or is planning to, they can PM me and submit it and I will upload it to the site for all to see."

Program Releases
  • Dr_Davenstein Releases Awesome OpenGL FB Demo - Dr_Davenstein has managed to crank a high-quality, high-speed 3D engine out of FB using the popular OpenGL library that anyone who doubts the power of FB should really check out. In the demo, you can run and jump through tunnels, over bridges and on platforms, and there are several 3D objects to check out. Aside from some touchy collision detection and control issues, this engine is great. Here's hoping that it is developed into a finished game.

    You can download the demo here: Freebio.zip

  • Jean Debord's FB Math Library - A Frenchman named Jean Debord has begun writing a math library for FreeBasic. You can check out the first version right here, or read the message forum announcement if you're so inclined.

  • OpenAL Ported To FreeBASIC - shiftLynx recently ported OpenAL, "a cross-platform 3D audio API appropriate for use with gaming applications and many other types of audio applications" to FreeBasic. According to shiftLynx, "It's currently being used by many commercial games, including Unreal 2, Unreal Tournament 2003, Unreal Tournament 2004 and Soldier of Fortune. (more titles...)." Visit the OpenAL news topic for more information.

  • FreeBasic Projects Galore - This topic is basically a list of a few dozen FB projects that people are working on. It's worth checking out if you want to see what other people in the FreeBasic scene are doing .

  • SJ Zero Releases Star Phalanx - Star Phalanx, a space shooter that SJ Zero began for his 48 hour FB programming competition last month, has been released.

  • RelSoft Will Port Space Impakto to FB - Rel announced that he will be posting his space shooter engine Space Impakto to FB. He describes this as "A space shooter engine written with QB+ASM as of now. Shows a cool and fast way to do homing, Pixel perfect collisions, ripped tiles and source included. Uses Rellib." You can find a demo of the QB version right here.

  • Sokoban By Retsyo - Retsyo has made a Sokoban game in FB that looks pretty cool. If you're not familiar with the game, here's retsyo's synopsis: "In this game, you are the man to push all horses into houses. You can only push the horse, but can not pull it. And you can not pull more than one horse everytime. If you or the horse is on the destination, red color is used, else blue color is used." The game is available for download here: sokoban.zip

  • Frantic Journey Will Be Ported To FB - Adigun A. Polack's beautiful space shooter, Frantic Journey will be rewritten in FreeBasic. Until this happens, though, you can pick up the Limited Edition version of the QB source code at the official Frantic Journey site. Adigun described his plans for the FB release: "I plan on even customizing this shmup to be very challenging and even as TRULY manic as ever. But also, I am to make this game really fair and as more fresh and exciting to play as the QB demo-version of this so that it is used and designed to be a blessing to you and to the shmup fans alike as well!!!" For more information, as well as a lot of screenshots and sourcecode downloads, check the website.

  • Angelo Mottola Releases Alternative FB GfxLib - QB legend Angelo Mottola is shaking up the FB scene, having just released a wonderful library that recreates many of QB's built-in graphical routines. Angelo describes the library as one "whose highlights are compactness (does not require external libs, goodbye SDL!), completeness (features all QB primitives, including arcs via CIRCLE, DRAW and PAINT) and compatibility with QB (doesn't require FLIP to keep screen updated as official GfxLib, and emulates modes 1, 2, 7, 8, 9, 10, 11, 12 and 13)." I highly reccomended this library to all FB programmers. You can find it on the Enhanced Creations++ website.

  • MystikShadows's FreeBasic IDE - MystikShadows joins the ranks of VonGodric and Nekrophidius this month, by releasing his own FB IDE which has many useful, unique features. Check out this post for screenshots or a download link.

Other News
  • MOoRPG Naming Contest - Z!re's running a competition / poll to help him come up with a new name for his upcoming FreeBasic roleplaying game, MOoRPG. So far, the suggestions have been pretty pathetic. Maybe you can help him out.

  • FreeBasic and PowerBasic Feud - FB programmers are rather territorial about their new baby, and they've recently been antagonizing PowerBasic programmers for using an "inferior" language. There have been numerous posts around both the QB and FB communities where people argue about which language is better. Here's one of them.



Gallery

Written by Pete

Every issue QB Express features a preview and exciting new screenshots from an upcoming QB game. If you would like your game featured, send in some screenshots!

This issue, we were lucky enough to receive information and screenshots for two upcoming FreeBasic games -- StarOdds32 by Na_th_an and Phantasm by Nekrophidius. So enjoy this special double-sized gallery!

StarOdds32 - Na_th_an

Na_th_an's FreeBasic remake of his point-and-click adventure game StarOdds is one of the best-looking FreeBasic games I've seen so far, with a simplistic cartoon art style that looks just splendid. (Check out the large screenshot below.)

Na_th_an sent me a very nice description of his upcoming game, so I've just pasted the entire thing into this article. (No point in recreating the wheel.) You can read the whole thing below. Enjoy!

-Pete

StarOdds was a game I coded during 1997 in my 486DX2. In that time, I didn't have Internet, so all I had was Qbasic 1.0 which shipped with MSDOS 6.0. Qbasic is really limited memory wise (even more than 4.5), and couldn't compile. I wanted to make a graphic adventure just like my fave games from Sierra or LucasFilms, and all I had to do it was Qbasic 1.0 or Moonrock 0.17 which I got from a magazine shareware CD.


A screenshot from the original 4-color version of Star Odds. Check out the review at V Planet!

Screenshot from the redrawn graphics made in 2000 (and then subsequently abandoned).

I tried to make it in SCREEN 7, i.e. EGA 320x200 in 16 colours, but as soon as I added more sprites I ran out of memory. Back in 1997 my coding skills were horrid. Probably it could have been done in 16 colours, but I just didn't know @£^$ about optimization memory-wise. So I decided to go even lower and use SCREEN 1, i.e. CGA 320x200 in 4 colours. Using PALETTE you could assign any of the 16 colours to the 4 attributes available, so it wouldn't look that bad, specially for me: I came from the 8 bits scene and I knew about lo-colour games.

The result was quite impressive, taking in account the tools I had to develop it. It featured a mouse driven interface with custom mouse cursors, point'n'click game dynamics, flicker free, fast GFX (even in uncompiled QBasic running in a 66 Mhz computer), big sprites, and "detailed" backgrounds which I made using 3DStudio for DOS v. 3.

I got internet in 1999 and, in late 2000, I discovered the QB/QBasic community through VPlanet. I thought it would be cool to send one of my best achievements to be reviewed. Mind you, "compiling" QB 4.5, graphics and sound libraries, EMS or XMS were things I could not manage using just QBasic and no internet, so this game was a true Achievement. I sent it in and after a while I discovered it got a "6"... 6 out of 35... It looked like Vance had an issue with lo-colour grapics. :)

I began redrawing the GFX, with a simple idea in my mind: using my recently discovered DirectQB and the QB 4.5 compiler to make an enhaced version. I made a bunch of GFX, but the last one in which I was working on got screwed when I had it almost finished due to a power failure. Then exams came, and I forgot about the project.

(You can view all of those old gfx here, if you are interested.)


This point-and-click adventure has great cartoonish graphics, as you can see in this screenshot. (I cropped off the bottom, since it was just black.)

In January, in the just middle of the fB craze, I remembered StarOdds in a conversation at QBnews forums, and found the reworked GFX. I thought it would be cool to make the new version in fB...

By the moment, all I have done is porting a GIF loader, making some auxiliary functions, and reworking a bit the GFXs. They suffered from really newbish defects, and used too many useless colours. I've been somewhat fixing them. I reduced the colour count to 16 for the backgrounds and 8 for the sprites. Now it looks great, and very retro. Check the screenshot above.

I plan using this thingo to develop a nice point'n'click engine in fB, which aetherFox and I will use for a bigger project. All I can say it is called "Backdoor Explossion" and that you will die laughing... when it's done.



Phantasm - Nekrophidius

Six or seven years ago, games like Nekrophidius's latest project, Phantasm were a dime a dozen. Back in 1998-2000, at the QB community's peak, RPGs were all the rage. Everyone and their mother was making one -- but it was very seldom that any game got past the engine demo phase. But at least people were coding stuff.

Somewhere along the line, the number of QB RPGs that went into development trickled to a handful, and then finally to almost none at the moment. It's been a long time since we've seen a new RPG... but now that FB is around, it looks like Nekrophidius is ready to start up the RPG hysteria again.

Nek's game, entitled Phantasm, is the first serious FreeBasic RPG I've seen in development, and so far it's looking pretty spiffy. Although so far there's just a simple engine demo available, the demo features attractive, colorful graphics, some nice music, and a solid walking engine. It's certainly nothing amazing, but it's a good foundation to build a game on.


NPCs will say different phrases to you depending on who you select as your lead character.

Nek began this game with the lofty goal of completing the entire thing within two days, kind of like what DarkDread used to do with the Secret of Cooey games a few years ago in his quick-and-dirty RPG coding competitions. Anyhow, here's the word straight from the man himself:

"This is an RPG I was cramming on to compete in SJ Zero's 48 hour FB compo. I didn't finish the game within the time frame and it's still unfinished, but here it is in its raw, in-progress form. It's a little primitive, okay it's very primitive, but it was a quickie so whaddyagonnado. :D Anyways, it uses PTCXL and is compiled in windowed mode so screenshots should be far too easy to take. [Thanks Nek, they were.] There's only one interesting feature about this game, and that's the lead character can be changed by going to the ingame menu (press ESC while playing) and selecting "Switch". Some dialogues change depending on who's the lead character, and the lead character gets party initiative in combat."



You can download the demo at: http://www.nodtveidt.net/phantasm.zip. "It's 3.96MB, but hey, it's from me so it's expected to be big. :D"

Will it ever get finished? Well, there's no timeframe in place, but maybe, just maybe it will get done: "I'll finish this game someday, I promise...hehehe :)" says Nekrophidius.


We need games for future Galleries! Send information and screenshots to Pete to have your game featured.


FreeBasic is our future. OUR Future.

Written by SJ Zero

The wheels of fate which are so apt at rolling merrily along against the wishes of those who would enjoy things to remain as they were continue to roll along, in all things. Both FreeBASIC and the passage of technology from 16-bit DOS to 32-bit Windows are unstoppable, and it's about time the community realized it and instead of fighting against the tiny, pathetic minutae which makes FreeBASIC only 99.9% compatible with old QB code, we start doing what we do best -- making do with what we have.

In the case of FreeBASIC, we have a LOT. Full windows and linux multimedia APIs including 3d graphics and sound(with more being added by the week), pointers, function pointers, full support for nearly every non I/O QB keyword(and most I/O commands too, now), math rivalling C in terms of speed, compilation on at least 3 OSes, we've got a LOT.



The black FreeBasic stallion rides in to save the day.

That said, I'm absolutely sickened by those who are throwing away this opportunity, one which 99% of communities like ours never dream of getting, to move into the future and get a fresh start (with all our code intact), over literal trivialities.

So far, the community's best coders have stepped up to plate to address every single concern that has popped up. Version .1 of FreeBASIC didn't come with a QB compatible graphics library. A library is now included which even allows you to use the old syntax in commands, such as line (x1,y1)-(x2,y2),colr. Another graphics library, code compatible with QB programs, doesn't even require flip() to be used. With all this, a single, ancient, largely useless(in the context of a quasi-modern game using page flipping, certainly) command has kept people from making the jump.

When FreeBASIC first came out, there were no decent IDEs for it. VonGodric stepped up to plate and gave us fbIDE, which tries to do a reasonable job of reinterpeting the QB IDE in Windows and largely succeeds. Some people didn't like it because the /wrong F-KEY was used for compile and run!/ It's madness, pure and simple. I have to wonder if, when Nekrophidius releases his IDE, we'll have people demanding he cease support for multiple file projects?

Programmers throughout the community seem to be forgetting they're programmers in many cases, and complaining about trifles which in nearly every case could either be coded by those complaining (many of freebasics coolest features weren't written by v1ctor! .11s new sdl tertiary lib support(ie. sdl_net, sdl_ttf, etc...) were done by people who just wanted those libs running! The qbgfx lib which ships with it was done by someone else who wanted to see a qbgfx lib as well!), or are fundamental differences between 16-bit and 32-bit code which cannot be reconciled without using QB in DOS.

Speaking of DOS, some have seen FreeBASIC, with it's win32 and linux support, as an attack on the venerable platform. Whine no more, my luddite brethren, because FreeBASIC has also been ported to DOS.

Perhaps I'm just cranky. Perhaps I'm out of line. Perhaps I've just seen what Open Source can do in the hands of QBers and I'm excited for the future of the community for the first time since 1999. Whatever it is, it's making me wish I could just tell everyone clinging to QB over such things to GROW UP, because unfortunately, the age of dos, such as it was, is over.

QB is dead. Long live QB through its bastard son, FB.

SJ Zero

P.S. Read my post on Qbasic News concerning QBXL. I'm sorry. This is actually my last qb related message anywhere until the situation is resolved. I vow to everyone who waits for the new issue that when I finish my exile, the next qbxl will be ready, and it will be the greatest issue ever.



Scorched Planets Review

Written by Zap

INFO

Scorched Planets by Joakim can be played either versus the computer, or versus another player on the same keyboard. The download is 351KB, which includes nicely commented source code, and a readme file to get you started. You can download the game at this address.

GAMEPLAY

If you've ever played Scorched Earth, or a similar game, the idea behind this game will be easy to grasp for you. Basicly, you aim your gun, set the velocity of your shot, and shoot. Your goal is to hit the opposite player, either computer controlled or played by a friend.

This particular game has a number of things to make this concept more interesting. First of all, it's set in outer space, but most joyful is that you can't just shoot in a straight line nor an arc, because the pull of gravity from the planets that exists in the playfield influence the flight of your shot.



Phew, saved by gravity. I drew the flight of the bullet so you can get an idea of how it works.

That feature makes the game a hundred times more fun to play, since you really have to think of how you will get to shoot your opponent, who will often be hidden away behind one or more planets. The first few time you play Scorched Planets, you will most likely have a hard time shooting the other player, but by trial and error you quickly grasp the concept of it all, and you will soon be able to have the bullet make intricate paths through the space towards its goal.

The playfields you fight your battle on are ofcourse randomly generated, which makes sure you will always be challenged when you play this game. Sometimes the playfields are sparse of planets, and sometimes there are alot, but I have yet to experience that there were too few or too many planets to be able to complete in crushing the other player.

There is one feature I miss, for all this good stuff I have just mentioned, and that is the possibility to upgrade your weapons between plays. Implementing that feature would have made this a really good game, but as this game was made for a short-lasting competition, I think it's perfectly understandable that it was not included, although I still miss it ;)

Gameplay Rating:
7/10
It's fun, addictive, but is missing some aspects to make it perfect.

GRAPHICS

The graphic side of Scorched Planets is around what you'd expect of a game created quickly for a competition. You don't get too many details of the playfield, for example there are no background stars or anything, but what there is, is pretty well done. The planets looks good and realistic, with shadows and all. This brings me on to a bad thing about those planets: There are only three different kinds. In the beginning you don't think too much of it, but later on looking at the same planets over and over can be a bit anoying. Again, I don't think the game should be blamed too much for this lack, becourse of the time-schedule within it was created. I'm just mentioning it as a thing that would be nice to see changed in a future version, if such a one is to be made.

Staying in the line of bad things about the graphics, I want to mention the space "ships" that you control. They look nice and all, but I'd expected to see them having a gun barrel or something like that, and got disappointed when I saw that all there were, were two red circles... Actually, the way you shoot off your bullet kinda reminds me of a game of minigolf.

The auther did implement a particle system, though, and that is pretty successful, although it would have looked even better if he had used some more particles when one of the players are hit. That part is a bit too "silent".

Graphics Rating:
6/10
Average, the images are good, it has effects, but it's lacking here and there.

SOUND EFFECTS & MUSIC

The first many times I played Scorched Planets, I played it without sound on, and it was fun. Then, I got to this part of the review section and figured that I would be better able to review the sound if I had actually heard it. So I turned up my sound and fired up Scorched Planets.

At first I got disappointed. The music, well, it is good, but it's really bad picked for a game of this type. It's silent, easy going, slow, "fine". Just not suitable for an action game.

Then I went on to play the game, and I got positively chocked this time. The sound effects are just as I had hoped. They really draw you into the game, heightens the fun, and makes you feel like you're in the middle of a dog fight in outer space.

SFX Rating:
9/10
Almost perfect. It hightens the gameplay a lot, and draws you into it.
Music Rating:
3/10
It's there, it sounds nice, but it was picked for a wrong game... Or the other way around.

CONCLUSION

This game has both arguments for and against - Overall it's well carried out, it's fun and addictive, and the sound effects boosts all these. On the other hand, the music seems totally out of place to me, and there's an importent feature that would give this game a gameplay among the bests, that isn't there. Im speaking of the ability to by improvements to your ship, here.

I know that you might not think it's fair to expect this feature to be included, because of the fact that this game was made for a short competition, but I think it is fair, since otherwise it might get a higher rating than a game that was actually finished, and that would be messy ;) So I've rated this game as-is.

Overall Rating:
63%
Fun, addictive, well carried out, although incomplete and flawed in some parts.

Download this game, or visit Zap's website, FreeBasic.tk.


Realistic 3D Modelling in QBasic: A Tutorial

Written by Mike Wechsler

We were pinned down and it didn't look good.

"Pete," I whispered, "if we don't make it through this, I want you to know that it's been a pleasure being your roommate."

"Don't talk like that!" Pete barked back as he gave me a sharp slap across the face.

I came to my senses and realized that Pete wouldn't let anything happen to me, not if he could help it. And I had a feeling that he could use QBasic to get us out of this bind.

That night was over 6 months ago, but I still remember it like it was just yesterday. It was our first night of school; Pete saved my life. I won't bore you with the details though, I am sure you have a healthy enough imagination to figure out what happened. Suffice to say, though, that it took a long night of coding, several "all-flavors-combined" Slushies and a startling awakening with a cold hand on my privates before I knew we were in the clear.

Some of you may be asking yourselves what this has to do with QBasic… Well I'll tell you: it has EVERYTHING to do with QBasic. After all, isn't there a little QBasic inside all of us? Isn't QBasic the common bond that we all share, from the lowliest level one dungeon troll to the highest level 14+ dragon mage? Isn't QBasic as described by Obi Wan Kenobi in the famous movie Star Trek, the Return of Khan, an energy field created by all living things that surrounds us, penetrates us, and binds the galaxy together? I think if you search within yourself you will find that the answer to all these questions is "yes".

Just the other day, I was driving my automobile when I saw a bumper sticker that seemed to sum up what I was thinking: "Don't mess with Texas!"

Now it's not that I have a particular affinity for Texas, in fact, the most I have seen of it is its rather lackluster airport. The fact stands, though, that 49 out of 50 states (roughly 98% of the country) know which state in particular not to mess with and I respect that. The only change I would make is that it would read "Don't mess with QBASIC!!!!!!!!1 LOLOL OMG!" because if there is one thing in life I know not to mess with it is QBasic… and I'll tell you why.

Several weeks ago, Pete and I had a falling out. I will take full responsibility for it; I should have known better than to interrupt him during his morning meditation. This was only the first in a long list of mistakes I made, though. Later that day I accidentally insulted Pete's favorite stand up comedian: Jeff Foxworthy. Pete had some harsh words with me but sent me on my way with only a tongue lashing. The straw that broke the proverbial camel's back, though, was when I accidentally "messed" with Pete's pride an joy… QBasic. You see, I was only experimenting, but I made this mistake of installing C++ on my computer. Somehow Pete found out about this and he was livid. You see, he won't allow any rival programming languages within 20 feet of his computer. He is not afraid; he just says QBasic could act up if it comes into conflict with other languages. I have always just trusted him on this point since he is the expert. Pete sent me to bed without dinner and did not talk to me for the next two weeks. He was really mad.

Finally, though, I figured out a way to win him back. You see, Pete is a sucker for colonial era wood carvings. I just so happened to come across a certain colonial era woodcarving that he was looking for to add to his collection. When I gave it to him, wrapped in a bow and tissue paper, I could see the tears in his eyes. Pete is a man of few words, but from the firm handshake he gave me, I could tell that we were friends again.

Some of you may be wondering what Pete's favorite websites are. Well, obviously Pete's QBasic Site is one of them. But after that, he really enjoys EricZapakin.tk, a website that he and I founded. Eric Zapakin is a friend of ours who we care about very much. Also, Pete encourages people to help me get myself a free item at http://www.FreeMiniMacs.com/?r=13995716 since he says he would give me anything I wanted if he could afford it. Pete also likes http://www.catsandrabbitsandmore.com for all his information on cats, rabbits and more!

In conclusion, I invite your feedback, but please send it to Pete to give to me since I am not allowed to use the computer after it gets dark outside. Next month I will attempt to answer reader questions if I get any and if not I will make some up and then answer them possibly.


Mike's not allowed to touch a computer after dark. To respond, email Pete at: pberg1@gmail.com


Chess Move Generator Competition

Organized by Neuro

In the past, QB Express has run its own competitions -- which have been a mild success thus far, but they haven't been as popular as we would have liked. Perhaps the reason is because there are just far too many competitions going on in the QB scene, and too few people to participate.

So instead of spending a lot of time starting and running a whole new competition, I've decided to back Neuro's new "Chess Move Generator" competition over at QBasic News. Check it out and enter it -- this is a cool challenge! Although technically it's a QB challenge, FB entries should be acceptable. Besides, the code will be virtually identical between FB and QB, since it's all text.

-Pete

This challenge can be found at this forum topic. Go there to ask questions, respond or submit your entries!

Alright here is the challenge:

Write a program which takes as input a chess board, like so:

rnbqkbnr
pppppppp
........
........
........
........
PPPPPPPP
RNBQKBNR
castle=KQkq
enpas=
turn=W

And then outputs all legal moves for that position, taking into consideration castling and en passant.

The input is shown from white's perspective (in other words, A8 is upper-left, H8 is upper-right, A1 is lower left, H1 is lower right)

and for the pieces:

The output should be a list of moves, seperated by either comma or new line (at your leisure).

And the output may be in coordinate notation, or, if you're really feeling up to the challenge, in Algebraic notation.

For example, for white castling kingside, E5-E7 is acceptable, the proper way, however would be "o-o"

Algebraic notation would be like this:

In algebraic notation, captures use a "x" instead of "-", and you use the name of the piece moving rather than just coordinates (e.g., Nf3), unless the piece moving is a pawn in which case all you need is the destinateion coordinate (e.g., e4).

Also in algebraic notation, en passant moves have a little "ep" at the end (example: exd3ep).

Also, if more than one piece of the same type can move to a given square, it must disambiguate by specifiying the unique rank or file of the moving piece (example: Ng-f3 which reads "knight on G to f3)

And, kingside castling is marked as "o-o" and queenside as "o-o-o"

Also, obviously it must print all the legal moves, and only the legal moves, so if it's white's turn it should not show moves that put white in check.


This would be an example output from the input shown above:

Legal Moves:
a2-a3
a2-a4
b1-a3
b1-c3
b2-b3
b3-b4
.....
h2-h4
end of list

Obviously this requires a basic knowledge of the rules of chess (not to mention an interest).

By the way, if you're wondering, I'm not trying to get anyone to do my homework for me (I've actually already completed this challenge but found it to be pretty fun and really get the mental juices flowing).

So... good luck

Peace
-- Eric / neuro


Visit the Chess Move Generator challenge thread to enter!


Comics

By Kevin (Rattrapmax6)

Rattrapmax6 returns this month with another horse comic.





Horse Comic




QBasic and What It Means To Me

Written by Brad Milison

I have no idea of what QBasic is. My friend Pete has tried at least twice to explain it to me, but it just soars above my head and never comes down. Maybe somewhere there’s an easy explanation to it. Maybe there is a Dummy’s Guide to QBasic. I doubt it, though. All I know is QBasic deals with computers and sometimes talks about games and the blocks used to make animation. Actually, I don’t know that for sure. Like I said earlier, I really have no idea what it means. I have visited the site, but, to use a popular expression, “It’s Greek to me.”

I decided to come up with my own definitions for what QBasic is and the following are what I came up with:



...

...

...

...

...

...

...

...

Okay, I’m literally sitting here typing right now and have no idea for any good definitions for QBasic.

It’s not even something that I can make something up just for fun. It’s so confusing to me that I can’t make jokes for fear of having a punchline rejected by someone who actually does understand QBasic. I wonder if I ever will understand it. Perhaps my ideas could inspire someone reading this, maybe even Pete, to make a “QBasic for Beginners” webpage where it offers the tiniest details on anything that QBasic deals with. There’s not much else for me to write. I’ve made my confusion apparent and clear, so now everybody knows. I’m sure QBasic may appeal to many in the way sushi does, but I’ll continue to be the one who observes and simply says, “I don’t get it.”


Brad lives in Holmes Hall, room 305. Pete lives in Holmes Hall, room 307. That is all.


I.F. Games Tutorial, Chapter 2

Written by Na_th_an

Last time we chatted we were discussing about how an IF engine works, and I explained the Parser and the Location Manager. Now it's time for hardcore stuff: the Objects Manager.

1.3. THE OBJECTS MANAGER

Remember last chapter, when we talked about exceptions? Yeah, those "special" things, what actually builds your adventure. Well, the Objects Manager deals with everything that's not an exception, i.e. with everything "normal". For example, when you type "open box", the Objects Manager will make that box open. When you type "examine rock", the Objects Manager will take care of it and show the description.

The Objects Manager is like the brains of your Interactive Fiction game. It is the true engine: makes everything work.

1.3.1. THE OBJECTS DATA TYPE

To begin with, we need to define some data types. The Objects Manager deals with objects in your game, so you need a powerful data type that's able to hold all the information your objects need. Not just their name, but also things like their description and some flags to tell whether the object is a light source or not, whether it is a container or not, whether you can wear it or not, whether it is a weapon or not... and things like size or weight, if you are really into making a complex engine.

For example, we could use something like this:

Const MAXOBJECTS = 255 ' Enough? :P Type ObjectType id As Integer ' an unique identifier. n As String * 20 ' object's name. d As String * 255 ' object's description. Lc As Integer ' where the object is located. Cont As Integer ' if the obj. is a container, where it contains. status As Integer ' status flags Weight As Integer ' object's weight Size As Integer ' object's size Capacity As Integer ' if the obj. is a container, object's capacity GN As Integer ' gender/number. End Type Dim Shared objs(MAXOBJECTS) As ObjectType ' Objects array.

This needs a bit of explanation. Let's go field by field explaining what's it for.

id as Integer

This will identify your object in the game. Every object should be assigned a unique number. You can be wondering... doesn't the array index suffice? The answer is no. You may use the array index, but using a separate id allows you to do some nasty stuff as many objects behaving similar or to categorize stuff easily. Leave it there, it may be useful in the future. We'll use it as a unique identifier in this tutorial.

n as String * 20

Your object's name, or how it will be called in the adventure. This has to be a word that's in the dictionary, so the parser understands it. For example, you have a green rock, name it rock, and add rock to the dictionary, as well as green. When the Objects Manager looks for an object the player has specified in his or her input, it uses this field.

d as String * 255

Your object's description. It should be a short text telling something about the object. This is the text which is displayed when the player's command is "examine object". Try to be gentle with descriptions. The player usually likes to read

Lc as Integer

This field tells the manager where the object is. It can be a valid location number (as defined in your locations file), or a special location. Special locations can be your inventory, the clothes you are wearing, your weapon, or another object. For example, I use "0" for the inventory, "-1" for your clothes, "-2" for your offensive weapon" and "-3" for your deffensive weapon. This way, if some object's Lc = 0 that means that it's in your inventory, if its Lc = -1 it means that you are wearing it, etcetera.

Cont as Integer

This is the location where an object contains another, if it is a container. This may sound puzzling. "the location where an object contains another", what the hell is that? You just read that every object has a Lc field telling where it is. Well, if we have an object "case" and an object "pen", you could put the pen inside the case. What would the pen's Lc field contain in such a case? i.e. where is the pen? you can put a 0 or a location number here, you need something special. Well, that's what "Cont" is. If we set the case's Cont to 1000, when the pen is inside the case its Lc will equal 1000.

Note that you can't reuse location numbers. 0, -1, -2, and -3 are reserved. Then you have your room numbers. That's why I always start containers location from 1000. I don't think I will ever need 1000 rooms, so that's fine.

Let's see another example: You have a room, which location id is 23. You have two objects, the pen and the case, which have Lc = 23, so they are in that room. The case is a container and has Cont = 1000. If you get the pen, its Lc will become 0, as it will go to your inventory. You get the case, its Lc will become 0 as well. You drop the pen, its Lc will become 23 again. You put the pen inside the case, the pen's Lc will become 1000. The case's Lc keeps being 0. You drop the case, the pen's Lc keeps being 1000, the case's is now 23. Get it?

Status as Integer

Status will contain the status flags. We will be using it as a binary flags container, using each of the number's bits to give information about the objects features. You have to decide which bit is for each feature. For example:

You can define more features, for example you can use a bit to tell if the object can be fired, i.e. it is a gun so it can be fired against someone, or whatever you want.

Obviously, you have to know how to work with single bits inside an integer value. It's not very hard. The formulae are easy to find and understand:

To toggle a bit, you just do status = status xor 2^n.

Weight as Integer

The object's weight. This can be extremely useful. We don't expect that the player can carry everything he or she wants. If you are carrying a big sword, by no means you can carry a heavy chair. Callibration can be difficult, and the best way to solve it is trial and error. For example, you can make a wallet weight 1, then make a chair weight 10. Everything is relative.

Size as Integer

This will specify how big your object is. This is used when attempting to put an object inside a container. By no means your engine should allow to put that heavy chair inside a wallet. When the engine is in the process of attending a "put a into b" command, it checks if the a's size is smaller than b's capacity. If that happens, it checks also if there's room inside b for a. You can have a wallet with capacity 5 and 10 pens with size 1, that menas that you can only put 5 of them inside the wallet.

Capacity as Integer

As mentioned above, the object's capacity. Of course, this only has a meaning if the object is a container, i.e. if bit 0 in its status field is set. See how everything works together?

GN as Integer

The objects gender/number. Gender is not needed in English. It is in Spanish, that's why I considered it - heh. Number is important. It will affect the engine so it builds the messages in plural or singular. For example you can consider 1 = singular, 2 = plural. That way, if you take a box, the message will be "you take it". If you take a pair of trowsers, the message will be "you take them". This is just cosmetic, but I consider such kind of details very important. Remember that the player will be reading a whole lot.

-

You can think about many more fields to add, depending on how your game will be. You could, for example, add a bit to the status variable for translucency, and a field for the degree of translucency, or you can reuse the capacity field for things like how much light a light source throws. For example, a match will suffice to light a small location, but it will fail to light a cave.

1.3.2. USEFUL GLOBAL PARAMETERS

You need to define some values as well which can be considered global. For example, how much weight your character is able to carry at a time, which object is he using as an offensive or deffensive weapon, and stuff like that. As I stuff everything inside a module, I use SHARED variables for this. Those only have meaning inside the module, but if you need them outside (for example, you could make your player get stronger using an exception), it's wise to write a SUB to modify its value from outside and a FUNCTION to read it:

Dim Shared maxWeight As Integer Function GetMaxWeight () As Integer GetMaxWeight = maxWeight End Function Sub SetMaxWeight (newMaxWeight As Integer) maxWeight = newMaxWeight End Function

That way, if you need to modify such values from outside, you just export the declarations to your module's .bi include file (i.e. add Declare Function GetMaxWeight() As Integer, etc... to ObjectsManager.bi). This avoid the need of having to declare inter-module globals which is not a very good practice.

1.3.3. DOWN TO THE MUDDY WATERS OF DESIGNING CODE

Basicly, the Objects Manager is built of a bunch of procedures, one for each possible command allowed in the game. Those procedures do the pertinent checks, and perform changes in the objects fields.

1.3.3.1. Checks.

For example, if the player writes "put pen into case", a procedure for "put" has to be called. In this procedure, several checks are done first:

(You may consider that the two last checks can be done with the latter, but this is done that way so the "error" messages (given if the condition fails) are more clear)

1.3.3.2. Action.

Once everything has been checked, the engine will put the pen inside the case, i.e., it will set the pen's "lc" field to the value which is in the case's "cont" field.

1.3.3.3. More procedures and functions.

As you may have noticed, there are some checks that have to be performed always, for example, checking if the objects are reachable or if the objects exist in the adventure. It's good practice (and sometimes it is completely needed, as we'll see very soon) to put these checks in easily callable functions of procedure.

For example, you need a recursive function to check if something is reachable from the current location. If you define it correctly, it won't harm your stack very much, and it will be fast enough. Note that there won't be many recursions in the average case. The pseudocode for that function would be something like this:

- Check if object is in current location id.
- If not, check if object is in the inventory.
- If not, check if object is worn.
- If not, for each container which is in the current location or in the inventory and is opened,
-> call recursively this function passing the object's "cont" field as location id.

1.3.4 OBSERVERS AND MODIFIERS

You need those to be able to code the exceptions. The objects array is private to this module, so it is good practice (and will come really handy later) to write a modifier and an observer function for each parameter you feel necesary. For example, you may want to add a couple of functions to modify/check every object attribute:

Sub SetContainer (objId as Integer, value as Integer) if value = 1 then objs(objId).status = objs(objId).status Or 1 else objs(objId).status = objs(objId).status And (Not 1) end if End Sub Function GetContainer (objId as Integer) as Integer GetContainer = objs(objId).status And 1 End Function

Exporting the declaration to these functions to the .bi file will allow you to alter or to check the attributes of your objects from any module.

--

And we are done by now. On next chapter, we'll see everything working together alongside a small and simple implementation in BASIC of everything which has been explained - i.e. a little game coded using these techniques. Stay tuned!


Na_th_an can be found at the QBasic News Forums, or you can visit his website.


Playing WAVE Files Through The Windows API

Written by aetherfox

I have seen many programs written with VB that want to have a 'beep' or 'ding' and they actually add a control and bust up the size of the program by an insane amount. Fortunately for clever people like me or you, the API has a nice little function that will do the work of playing a wave file. And with little enhancements to the function, you could even use it in a simple game!

The API call you need to use to access this magical function is as follows:

Private Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long

The function has two parameters:

The second parameter of this function is very useful to play your wave file in different ways. Maybe you want it to loop, maybe you want to play it once - this is how to do it. Most API calls have handy-dandy constants to make life easy, and the ones for this are:

Const SND_ASYNC = &H1
Const SND_LOOP = &H8
Const SND_NODEFAULT = &H2
Const SND_SYNC = &H0
Const SND_NOSTOP = &H10
Const SND_MEMORY = &H4

If we wish to use more than one of these constants in conjunction, we link them with an "or" statement so that both constants will have an effect. For example, it is best to use SND_ASYNC along with SND_LOOP to ensure that the program can continue functioning while the looped wave file is playing. If we used SND_SYNC with SND_LOOP, we would never get control back to our program!

Example:

sndPlaySound App.path & "\ding.wav", SND_ASYNC or SND_LOOP

The constants do the following:

So to play the sound 'monkey.wav' that is stored in the '\sounds' folder of the application path by looping it, I would do:

sndPlaySound App.Path & "\sounds\monkey.wav", SND_LOOP

To use more than one constant, then link them with Or to make sure they will have an equal effect.

While this method is simple, in many cases it will suffice. For advanced handling of sound, use DirectSound. This method however, will work on every language that can handle the API (the way to call the API will obviously be different). The major example here is freeBASIC; instead of using FMOD to play a wav file, you can use this method.

aetherFox
avinashvora [at] gmail [dot] com.
http://avinash.qbxl.net


Download this tutorial, or contact aetherfox.


Music Composition

Written by Matt2Jones

Dun - Dun

Part I - Justification

This is probably gonna be the hardest part of the article; Explaining why the fuck I wrote it. What useful purpose could an artical on score-composition serve in... Now - the era of sequencers and excessive samples and [insert other technicle buzzwords]... I dunno, EQ pedals and shit?

Realisticly it's not gonna be of use to most of you. I only know of one music program that lets you write the notes onto the musical stave thing, and thats a midi program for windows 3.1, which is technically redundant and unfashionably 'retro' at the moment, and if any of you have a more advanced program that allows for musical notation, you know more then I do about the subject.

Never the less, I persist. Basicly I find this shit interesting and explaining it to someone else is a good way to figure it out for definate yourself (paraphrased, see Jaxom, White Rider), and, for those of you who share my interest, midi's can be, with just the touch of a button! (thank you marketing devision), converted to really sweet sounding wav's/mp3's using all your amazing samples and EQ pedals...

I mean, if they were good enough for Beethoven/Tchaikovskii(Jesus christ how do you spell his fucking name?)/Motzart... and to a lesser extent Bach, old-school score's should be good enough for you, the modest *B coder.


See the '*' is a wild card, indicating either 'Q' or 'P' or 'F', which I here has pretty much converted the entire nation while I was gone, and while I don't want to leave QB, I don't want to unnessesarly offend someone today either, so I play it safe - that's Politics!.

PART II - Rudiments

Here be basic knowlage of music to Jnr cert standard.

I Should explain. Everything contained her-in is the stuff I have learned in the past year and 4 months since I took up music for leaving cert in my school, cause they wouldn't let me leave a blank spot on my time table (power tripping bastards...). Because I'm doing it as an examination subject I'm not getting a complete musical education, I'm just being told what they're gonna ask me in June, so that's all I can tell you. Any 'topics' I skip I skip because I don't need to be taught them. Apologies all round.

Now to the shit:

Notes:

Musical 'sounds' are divided into seven (really eleven) notes, which loop infinatly. The seven musical notes are:

A B C D E F G

Wow, that was patronising.

Well, actually the notes are

A C# B C C# D D# F F# G G#

Notice that between each pair of notes (eg. A and B) there is a Sharp note (#), except for Between B + C, and E + F. This is a peculiarity that exists in reality, but when you're writing the score you don't have to worry about it.

This is so stupidly simple you may not understand it until you see the point of it.

Keys:

Every song starts with the First note. How Profound. The first note you is then followed by a second note, and then a third (come on, you've all heard music before), but how do you choose what the first, second, third etc notes are? Which will sound good? Is there any way of knowing? [I can't think of a way to conclude these rhetorical quips so I'll start a new paragraph]

The first note of a song will allways sound good, because in music what your hearing is not the notes, but the differences between the notes (I remember there was a speach in Angle about this once), so the first note will always sound fine. However, once you've played one note, you are now limited in choice as to which notes you can follow this with without the music sounding dissonant, and after choosing that second note, your choices for a third are even more limited, often in different ways. The Concept of a 'Key' is an easy means of predicting which notes can come next, taking into account all the previous notes.

In a Concice, Memorable, Simple and Obvious (but also kind of wrong) nutshell, it is this.

If the first note is 'C', then you are in the Key of 'C', and the notes that can pleasently follow are

C D E F G A B ... repeating on...

Look familiar? Thats because its the alphabet you retard.

Anyway, one of the proporties of the key of C is that all the notes that sound good when played after it are 'Natural' notes (ie. Not Sharps #'s or Flats b's).

If you look at the spaces between these notes, ie. the notes from the eleven mentioned earlier that have been skipped, you will find a pattern:

skip one, skip one, don't skip any, skip one, skip one, skip one, don't skip any

This is the pattern you can apply to any note from the eleven, to find all the other notes in it's Key. For example: the Key of A is

A skip one B skip one C# don't skip any D skip one E skip one F# skip one G# don't skip any

or

A B C# D E F# G#

These are the 'intervals' for a Major Key, Ie. one that sounds happy, and can be applied to any note to get the notes in its Major Key. Its important to remember that the "Key of C" is call the "Key of C major", even though the major is omitted, because there are other types of Keys, with different intervals between the notes, and mixing them up would be disasterous.

To Recap:

The Key is the first note you play, which determines the notes you can play afterwards in the song.

Chords and Harmony:

So far we've discussed Notes, and playing notes one after another so that they sound good in sequence, but what about playing notes at the same time? This is called Harmony, and a simple way to get good results is to use Chords. Anyone who knows anything about music is laughing so hard at me right about now.

Think of a Chord like a Key for the moment, like a stencil you plonk down on a note to reveal what other notes would sound good played at the same time (I'm proud of that similae), but while the Key was a stencil you... No wait, lets call them bitmasks! We're all coders here after all... (wow, I'm really getting into this...)

Anyway, while you AND the KeyBitMask with the ListOfNotes... Okay this is stupid. While the stencil for the Keys was laid over the list of all notes to reveal the notes in the key, the stencil for the chord is laid over the list of notes IN THE KEY YOUR IN to reveal all the notes in the Chord. As follows:

Key of C

C D E F G A B
1 2 3 4 5 6 7

So C is the 1st note of the key, D is the 2nd, E is the 3rd, F is the 4th, G is the 5th, A is the 6th and B is the 7th.

Now the Chord of C consists of

C E G  ... Repeat indefinatly
1 3 5

Now look at the Relationship between these three notes, in terms of the Key of C. The first one, C, is called the Root note, so this is the Chord C, the middle note in the Chord is E, this is called the '3rd' because there is a '3' under it, and the last note is called the '5th', because there is a five under it. In terms of the key the intervals between each note in the chord are:

skip one, skip one, skip two

Why skip two? To get back to C again, in the Octave above (ie. Second iteration of the notes 1 to 7).

This is now the formula you use to get the notes of a chord, from the notes in a key.

Examples:

Key of C:
C D E F G A B

Chord of F:
F A C

Chord of G:
G B D

Now lets examine the notes in the chords further.

Key of C Chord I - C C E G

The 'intervals' between (Notice I am putting intervals within inverted comma's, this is because I am not talking about actual musical intervals, which are specificly defined, but the word is useful to help describe this phenominon) actual physical musical notes, relative to the list of eleven notes I gave earlier, not the notes in the key are as follows:

Skip three, Skip two, Skip four

Now lets plonk the chord stencil down on the next note in the key, D, and see what the 'intervals' are between the notes, relative to the list of eleven I blah blah blah.

Key of C

Chord II - D

D F A

Skip two, Skip three, Skip four

Oh Fuck they aren't the same. Whatever are we to do.

They formulae I've given you are not wrong, and the 'intervals' between the notes in the different chords should be different, and this is the explanation.

There are patterns of 'intervals' that, when applied to a note result in other notes which sound harmonious when played alongside the Root. Like keys, which I'll explain more of later, there is more then one pattern which can be used, and each of these patterns has the desirable side effect of evoking an emotional reaction from a well balanced human being (or you). This is how films manipulate you with sound so easily. The four 'patterns' of 'intervals' that I know of are:

Major, Minor, Diminished, Augmented

Which are, as I mentioned, names for styles of Keys and styles of Chords.

Now unfortunatly, while a C Major chord sounds nice and happy by itself, and a D major chord sounds equally happy and nice by itself, together they sound shitty. Why? Lets examine it.

'Intervals' for Major Chord: Skip three, Skip two, Skip four

Chord C -- C skip three E skip two G  -- C E  G

Chord D -- D skip three F# skip two A -- D F# A

Now, in the Key of C, there is no F#, so playing C major, followed by D major in the Key of C, would sound all fucked. So what Chords can you play on D? Only One it turns out. Minor.

Now to save me the trouble of working out every fucking chord and note and key I'm gonna tell you straight up.

In a Major Key, the Chords are as follows

Chord I  - A Major Chord	-	eg. C
Chord II - A Minor Chord	-	eg. Dm
Chord III- A Minor Chord	-	eg. Em
Chord IV - A Major Chord	-	eg. F
Chord V  - A Major Chord	-	eg. G
Chord VI - A Minor Chord	-	eg. Am
Chord VII- A DIMINISHED Chord-	eg. Bdim

What does this mean for you? Well, it doesn't effect how you write the music at all, thanks to the wonderful invention of keys, but its nice to know that when you play a chord on D, in the Key of C, that its a minor chord, and so on.

Note:

Use this knowlage to your own dramatic effect.

Okay, I actually think thats it for the Rudiments. You know have the theory to understand the next installment of the tutorial, which involves actually writing music.

For the record the following chapter should be:

1. Rudiments

2. Introduction to Scores (key signatures etc), Using Winjammer.

3. Chord progressions and writing 'left hand'/'lead' music

4. Modulating, Writing Bass Notes, writing with Up Beats, Writing drums

Matt2fuckingjones.

Email me with comments/critisism/questions: Matt2jones@yahoo.com


And on a Serious Note:

For anyone with actual musical knowledge, if I have made any major fuck ups in my explanations I would, first of all like to be notified, but secondly I would prefere to be notified by email, cause its private and I'd like to fully understand the situation before I publicly embarass myself, looking forward to your (inevitable) co-operation,


Download a formatted RTF version of this tutorial.


Text RPG Tutorial

Written by Nixon

Making a Text RPG can be very easy. You need to know exactly what you want it to do though. Things like is it real time or turn based. Can you shoot, can the player pick up things, are you going to have a map editor. These effect what kind of map data you use. Some are easyer then others because they allow less code to move around, and are easier to understand. Some are alittle difficult to use and have more code.

I have programmed as many possible types of maps that can be used. These can be combined to make use of different features. They all hold the same practical idea.

I will start with a simple one. If you copy the code and paste it in a new text file and name it "textrpg.bas". then open it in QBasic it should work unless you screwed it somehow, If you didn't it could have been me.

CLS 'gets map ready DIM map(100, 100) FOR y = 1 TO 10 FOR x = 1 TO 10 READ map(x, y) IF map(x, y) = 0 THEN LOCATE y, x: COLOR 2: PRINT CHR$(176) IF map(x, y) = 2 THEN LOCATE y, x: COLOR 6: PRINT CHR$(176) IF map(x, y) = 10 THEN LOCATE y, x: COLOR 10: PRINT CHR$(6) IF map(x, y) = 11 THEN LOCATE y, x: COLOR 7: PRINT CHR$(111) NEXT x NEXT y 'sets player x and player y px = 2 py = 9 'start of big loop top: 'gets what is behind player bg = SCREEN(py, px) bgc = SCREEN(py, px, 1) 'puts player on the screen LOCATE py, px: COLOR 15: PRINT CHR$(2) 'checks to see if a key is pressed DO: P$ = INKEY$: LOOP UNTIL P$ <> "" 'clears player off screen and replaces with background LOCATE py, px: COLOR bgc: PRINT CHR$(bg) 'checks to see if a certian key was pressed so that the player x or player y 'can be moved to a new location. IF P$ = "8" AND map(px, py - 1) <= 9 THEN py = py - 1 IF P$ = "5" AND map(px, py + 1) <= 9 THEN py = py + 1 IF P$ = "6" AND map(px + 1, py) <= 9 THEN px = px + 1 IF P$ = "4" AND map(px - 1, py) <= 9 THEN px = px - 1 'goes back to the top GOTO top 'map data DATA 10,10,10,10,10,10,10,10,10,10 DATA 10,00,00,00,00,00,00,00,02,10 DATA 10,00,00,00,00,00,11,02,02,10 DATA 10,00,00,00,02,02,02,02,10,10 DATA 10,00,00,00,02,10,00,00,00,10 DATA 10,00,00,02,02,00,00,00,00,10 DATA 10,00,02,02,00,10,00,00,10,10 DATA 10,00,02,00,10,10,10,00,00,10 DATA 10,02,02,00,00,00,00,00,00,10 DATA 10,10,10,10,10,10,10,10,10,10

Simple huh?

Most of this makes sense. The only thing you might be confused about is why I use 00,02,10,11 in the data instead of using 1,2,3,4. Well if you look at my code in the keys part you will notice it checks the map for something. "map(px, py - 1) <= 9" This checks to see if the position it wants to move to is a walkable tile or a wall. I have used 00-09 as walkable tiles and 10-99 as wall tiles. This way I'm setup for when I add more walkable tiles. If you really want to be safe you can have 0-50 as walkables and 50-whatever as walls.

If you wanted to make items laying around then you should use a fake and chck when the player ontop of it by using

IF map(px, py) = 3 THEN map(px, py) = 0: bg = 176 : bgc = 2: score = score + 1

Put it after the keys so it happens as soon as you move onto it. It checks to see if the place where the player is a 3 on the map and if it is then it sets that part of the map to a normal walkable tile.


Now that you have taken all that code in you are ready to see the next map type.

CLS 'gets map ready DIM map(100, 100), tiles(100) 'reads tiles data READ amount FOR i = 1 TO amount * 4 READ tiles(i) NEXT i 'reads map FOR y = 1 TO 10 FOR x = 1 TO 10 READ map(x, y) LOCATE y, x 'Prints right tile in right place FOR i = 1 TO 100 STEP 4 IF map(x, y) = tiles(i) THEN COLOR tiles(i + 2) PRINT CHR$(tiles(i + 1)) EXIT FOR END IF NEXT i NEXT x NEXT y 'sets player x and player y px = 2 py = 9 'start of big loop top: 'gets what is behind player bg = SCREEN(py, px) bgc = SCREEN(py, px, 1) 'puts player on the screen LOCATE py, px: COLOR 15: PRINT CHR$(2) 'checks to see if a key is pressed DO: P$ = INKEY$: LOOP UNTIL P$ <> "" 'clears player off screen and replaces with background LOCATE py, px: COLOR bgc: PRINT CHR$(bg) 'checks to see if a certian key was pressed so that the player x or player y 'can be moved to a new location. IF P$ = "8" AND tiles((map(px, py - 1) * 4)) = 0 THEN py = py - 1 IF P$ = "5" AND tiles((map(px, py + 1) * 4)) = 0 THEN py = py + 1 IF P$ = "6" AND tiles((map(px + 1, py) * 4)) = 0 THEN px = px + 1 IF P$ = "4" AND tiles((map(px - 1, py) * 4)) = 0 THEN px = px - 1 IF P$ = CHR$(27) THEN END 'goes back to the top GOTO top 'map data 'Tile data DATA 5 'tiles (Tile number, ASCII Character, Color, 0=walkable 1=wall) DATA 1,176,2,0 DATA 2,6,10,1 DATA 3,177,6,0 DATA 4,176,9,1 DATA 5,111,7,1 'The map DATA 04,04,04,04,04,04,02,02,02,02 DATA 04,04,04,04,04,01,01,02,01,02 DATA 04,04,04,04,04,01,01,01,02,02 DATA 04,04,04,04,01,02,01,01,01,02 DATA 02,01,04,04,02,01,01,02,01,02 DATA 02,01,02,01,01,03,03,03,03,02 DATA 02,01,03,03,03,03,05,01,02,02 DATA 02,03,03,01,01,01,02,01,01,02 DATA 02,03,01,01,05,01,01,01,02,02 DATA 02,02,02,02,02,02,02,02,02,02

This one is a little more complex. I only just came up with it. This one makes it easier to make a new tile. The tile can be any number and it doesn't effect the where the player moves. The 0 and the 1 change that.

DATA 1,176,2,0

The 0 at the end tells the player that he can move onto it, if it was a 1 then the player could not walk on it. This is the code it uses to check if it can go somewhere.

IF P$ = "8" AND tiles((map(px, py - 1) * 4)) = 0 THEN py = py - 1

Looks the same as the the code in the 1st program. It really is very much the same. It goes and sees what tile number is in the position and then if the tile has a 0, if so then the player moves.

Those two are pretty good but I still have more. Heres the 3rd one. It is kind similar to the one above.

CLS 'gets map ready DIM map(100, 100), walls(100, 100) FOR y = 1 TO 10 FOR x = 1 TO 10 READ map(x, y) LOCATE y, x COLOR VAL(MID$(STR$(map(x, y)), 1, 2)) PRINT CHR$(VAL(MID$(STR$(map(x, y)), 3, 6))) NEXT x NEXT y FOR y = 1 TO 10 FOR x = 1 TO 10 READ walls(x, y) NEXT x NEXT y 'sets player x and player y px = 2 py = 9 'start of big loop top: 'gets what is behind player bg = SCREEN(py, px) bgc = SCREEN(py, px, 1) 'puts player on the screen LOCATE py, px: COLOR 15: PRINT CHR$(2) 'checks to see if a key is pressed DO: P$ = INKEY$: LOOP UNTIL P$ <> "" 'clears player off screen and replaces with background LOCATE py, px: COLOR bgc: PRINT CHR$(bg) 'checks to see if a certian key was pressed so that the player x or player y 'can be moved to a new location. IF P$ = "8" AND walls(px, py - 1) = 0 THEN py = py - 1 IF P$ = "5" AND walls(px, py + 1) = 0 THEN py = py + 1 IF P$ = "6" AND walls(px + 1, py) = 0 THEN px = px + 1 IF P$ = "4" AND walls(px - 1, py) = 0 THEN px = px - 1 IF P$ = CHR$(27) THEN END 'goes back to the top GOTO top 'map data (color + ASCII character) DATA 01176,02176,03176,04176,05176,01176,02176,03176,04176,05176 DATA 02176,00000,00000,00000,00000,00000,00000,00000,00000,04176 DATA 03176,00000,00000,00000,00000,00000,00000,00000,00000,03176 DATA 04176,00000,00000,06176,06176,06176,00000,00000,00000,02176 DATA 05176,00000,06176,06177,06177,06177,06176,00000,00000,01176 DATA 06173,00000,06176,06177,05178,06177,06176,00000,00000,00176 DATA 07176,00000,06176,06177,06177,06177,06176,00000,00000,01176 DATA 08176,00000,00000,06176,05178,06176,00000,00000,00000,02176 DATA 09179,00000,00000,00000,00000,00000,00000,00000,00000,03176 DATA 10176,09166,08156,07176,06136,05176,04176,03176,02124,01176 'wall data DATA 1,1,1,1,1,1,1,1,1,1 DATA 1,0,0,0,0,0,0,0,0,1 DATA 1,0,0,0,0,0,0,0,0,1 DATA 1,0,0,0,0,0,0,0,0,1 DATA 1,0,0,0,0,0,0,0,0,1 DATA 1,0,0,0,1,0,0,0,0,1 DATA 1,0,0,0,0,0,0,0,0,1 DATA 1,0,0,0,0,0,0,0,0,1 DATA 1,0,0,0,0,0,0,0,0,1 DATA 1,1,1,1,1,1,1,1,1,1

Nice eh? This makes use of moulding information together. This has saved space. I could have blended then wall data into the map data by changing the data in the map to "101760" which breaks up into

color: 10 character: 176 wall 1/0: 0

As a challenge you might want to do that and also make an editor to make maps. I recconmend that you make an editor for that data, because it aint all that much fun to put in. If I get enough e-mails(lets say 1) I will wright a tut on editors and make one just for this.

This code is a little different for when it displays it. it first has a look at the first two digits of the number

COLOR VAL(MID$(STR$(map(x, y)), 1, 2))

this tells it what color it will be. The next line finds out what the last 3 digits are and uses them with CHR$()

PRINT CHR$(VAL(MID$(STR$(map(x, y)), 3, 6)))

When the player moves it checks the 2nd map to see if there is a 0 on the position it wants to move too. If it is a 1 it won't move there, thus acting like a wall. Simple huh?

I'll give one last example of a map and then show you how to link up a couple of maps and store the data of each map in a tidy easy to use way.

CLS 'gets map ready DIM map(100, 100) FOR y = 1 TO 10 FOR x = 1 TO 10 READ map(x, y) IF map(x, y) = 0 THEN LOCATE y, x: COLOR 2: PRINT CHR$(176) IF map(x, y) = 2 THEN LOCATE y, x: COLOR 6: PRINT CHR$(176) IF map(x, y) = 10 THEN LOCATE y, x: COLOR 10: PRINT CHR$(6) IF map(x, y) = 11 THEN LOCATE y, x: COLOR 7: PRINT CHR$(111) NEXT x NEXT y 'sets player x and player y px = 2 py = 9 'start of big loop top: 'gets what is behind player bg = SCREEN(py, px) bgc = SCREEN(py, px, 1) 'puts player on the screen LOCATE py, px: COLOR 15: PRINT CHR$(2) 'checks to see if a key is pressed DO: P$ = INKEY$: LOOP UNTIL P$ <> "" 'clears player off screen and replaces with background LOCATE py, px: COLOR bgc: PRINT CHR$(bg) 'checks to see if a certian key was pressed so that the player x or player y 'can be moved to a new location. IF P$ = "8" AND SCREEN(py - 1, px) <> 6 THEN py = py - 1 IF P$ = "5" AND SCREEN(py + 1, px) <> 6 THEN py = py + 1 IF P$ = "6" AND SCREEN(py, px + 1) <> 6 THEN px = px + 1 IF P$ = "4" AND SCREEN(py, px - 1) <> 6 THEN px = px - 1 IF P$ = CHR$(27) THEN END 'goes back to the top GOTO top 'map data DATA 10,10,10,10,10,10,10,10,10,10 DATA 10,00,00,00,00,00,00,00,02,10 DATA 10,00,00,00,00,00,11,02,02,10 DATA 10,00,00,00,02,02,02,02,10,10 DATA 10,00,00,00,02,10,00,00,00,10 DATA 10,00,00,02,02,00,00,00,00,10 DATA 10,00,02,02,00,10,00,00,10,10 DATA 10,00,02,00,10,10,10,00,00,10 DATA 10,02,02,00,00,00,00,00,00,10 DATA 10,10,10,10,10,10,10,10,10,10

Now this one is almost the same as the 1st program. The only difference is that instead of check the map to see if it can move it checks the screen. This can useful sometimes but others useless. If you printed character 006 randomly over the screen and did not have a map for it then this is useful. It would create a forest type type effect also. You could put any other character on the screen and you would be able to walk over it because it is not character 6. To change that just change the sixs in the keys part to anothe character, for example 219

IF P$ = "8" AND SCREEN(py - 1, px) <> 219 THEN py = py - 1 IF P$ = "5" AND SCREEN(py + 1, px) <> 219 THEN py = py + 1 IF P$ = "6" AND SCREEN(py, px + 1) <> 219 THEN px = px + 1 IF P$ = "4" AND SCREEN(py, px - 1) <> 219 THEN px = px - 1

Instead of checking the character yo could check the color. to do that all you have to do is add a 1. Like this

SCREEN(py - 1, px,1) <> 4

If you use that instead you will not be able to walk on anything that is dark red.

Now for the end of this. I will show you a program that can change to different maps easily. After all it would be stupid not to show this in a RPG tut, because thats one of the main features.

CLS 'gets map ready DIM map(10, 11, 11) FOR m = 1 TO 3 FOR y = 1 TO 10 FOR x = 1 TO 10 READ map(m, x, y) NEXT x NEXT y NEXT m 'sets player x and player y px = 2 py = 9 'sets the map you start on m = 1 'draws the current map you are on redraw: FOR y = 1 TO 10 FOR x = 1 TO 10 IF map(m, x, y) = 0 THEN LOCATE y, x: COLOR 2: PRINT CHR$(176) IF map(m, x, y) = 2 THEN LOCATE y, x: COLOR 6: PRINT CHR$(176) IF map(m, x, y) = 10 THEN LOCATE y, x: COLOR 10: PRINT CHR$(6) IF map(m, x, y) = 11 THEN LOCATE y, x: COLOR 7: PRINT CHR$(111) NEXT x NEXT y 'start of big loop top: 'gets what is behind player bg = SCREEN(py, px) bgc = SCREEN(py, px, 1) 'puts player on the screen LOCATE py, px: COLOR 15: PRINT CHR$(2) 'checks to see if a key is pressed DO: P$ = INKEY$: LOOP UNTIL P$ <> "" 'clears player off screen and replaces with background LOCATE py, px: COLOR bgc: PRINT CHR$(bg) 'checks to see if a certian key was pressed so that the player x or player y 'can be moved to a new location. IF P$ = "8" AND map(m, px, py - 1) <= 9 THEN py = py - 1 IF P$ = "5" AND map(m, px, py + 1) <= 9 THEN py = py + 1 IF P$ = "6" AND map(m, px + 1, py) <= 9 THEN px = px + 1 IF P$ = "4" AND map(m, px - 1, py) <= 9 THEN px = px - 1 IF P$ = CHR$(27) THEN END IF px = 11 THEN px = 1 IF m = 1 THEN m = 2: GOTO redraw END IF IF px = 0 THEN px = 10 IF m = 2 THEN m = 1: GOTO redraw END IF IF py = 11 THEN py = 1 IF m = 2 THEN m = 3: GOTO redraw END IF IF py = 0 THEN py = 10 IF m = 3 THEN m = 2: GOTO redraw END IF 'goes back to the top GOTO top 'map data DATA 10,10,10,10,10,10,10,10,10,10 DATA 10,00,00,00,00,00,00,00,00,10 DATA 10,11,00,00,00,00,11,00,00,10 DATA 10,00,00,00,02,02,02,02,10,00 DATA 10,00,00,00,02,10,00,02,02,02 DATA 10,00,00,02,02,00,00,00,00,00 DATA 10,00,02,02,00,10,00,00,10,10 DATA 10,00,02,00,10,10,10,00,00,10 DATA 10,02,02,00,00,00,00,00,11,10 DATA 10,10,10,10,10,10,10,10,10,10 DATA 10,10,10,10,10,10,10,10,10,10 DATA 10,00,00,00,00,00,10,00,10,10 DATA 10,00,00,00,11,00,00,00,00,10 DATA 00,00,00,00,00,00,00,00,10,10 DATA 02,02,02,02,00,00,10,00,00,10 DATA 00,00,00,02,00,10,00,00,00,10 DATA 10,00,00,02,00,00,00,00,00,10 DATA 10,10,00,02,02,02,00,10,00,10 DATA 10,00,00,11,00,02,00,00,00,10 DATA 10,10,10,10,00,02,00,10,10,10 DATA 10,10,10,10,00,02,00,10,10,10 DATA 10,00,00,00,00,00,00,00,00,10 DATA 10,00,00,00,00,00,00,00,00,10 DATA 10,00,00,00,00,00,00,00,00,10 DATA 10,00,00,00,00,00,00,00,00,10 DATA 10,00,00,00,00,00,00,00,00,10 DATA 10,00,00,00,00,00,00,00,00,10 DATA 10,00,00,00,00,00,00,00,00,10 DATA 10,00,00,00,00,00,00,00,00,10 DATA 10,10,10,10,10,10,10,10,10,10

The big difference in this program is the 3 different maps. To switch from map to map all I had to do was change m to the desired map number so that that map data was used. When you reach the end of the map it checks to see what map you are on and then send you to the map that you need to goto. You can have many more levels and to change to a different map you can change what m equals. eg instead of going to map 2 you could change the

IF m = 1 THEN m = 2: GOTO redraw

to

IF m = 1 THEN m = 3: GOTO redraw

This would take you to map 3 and put you ontop of a wall because map 3 was not designed to link to map 1. All ya have to do is change the map data to make it look like you can.

Experiment with all of these and mix and match the map data use. This way you will be able to understand the code better and make better things. Try adding extra features to the programs like in the last one, try adding more maps. Make more tiles. Even try to make NPC's, people or monsters walk around on the map as well.

I hope this has inspired you, or at the least made you consider making a text RPG, or anyother text game. I hope to release another tutorial on Editors or AI's next month. I can't believe I wrote all this in one afternoon.

If you have any problems e-mail me at cant.get.nixon@gmail.com

or visit Pure Text and post on the forum www.Pure-Text.com

-Nixon


Download this tutorial: textrpg.txt


Z-clipping Triangles

Written by Shashi Ponraja

I decided to write this short tutorial to make absolutely sure I didn't forget how to clip 3d triangles. Then I realized I could post it on QB Express as

I decided to write this short tutorial to make absolutely sure I didn't forget how to clip 3d triangles. Then I realized I could post it on QB Express as well! So why the hell not.

Z-clipping Triangles

Whenever you have a point in 3d space, it will either be in front(z >0), behind you (z<0) or on you (z=0). The easiest way to eliminate this problem would be to make sure all points of a triangle are visible, so if one isn't visible the triangle isn't drawn. Of course, as I discovered, this looks terrible for large polygons, creating dumb-looking see through glitches. So what's the remedy? Remove the parts of the triangle that are not visible, leaving only the visible parts. I suggest for the code you use double-precision(defdbl a-z for the poly clipping sub), I used that cuz sometimes errors occurred that I thought might have been because of accuracy.

Starting off....

Let's say you have each point of your triangle in an array of vertex(3) as vtxinf
where

type vtxinf x as single y as single z as single u as single 'x-coord in texture map, I use between 0..1 but you can use whatever is appropriate v as single 'y-coord in texture map, I use between 0..1 but you can use whatever is appropriate end type

The 3 points are in vertex(0), vertex(1), vertex(2). (The extra element is there for a reason.....as you might expect)

To simplify coding this routine, we could start off by arranging it so the vertex with the largest z starts at the top, like this

If vertex(0).z < vertex(1).z then swap vertex(0).x, vertex(1).x swap vertex(0).y, vertex(1).y swap vertex(0).z, vertex(1).z swap vertex(0).u, vertex(1).u swap vertex(0).v, vertex(1).v endif

And so on and so forth until vertex(0).z is highest, and vertex(2).z is the lowest.

Now to quickly test whether any portion of the polygon is visible on-screen, just check this

if vertex(0).z > zclipplane then polyvisible = true 'where zclipplane is the minimum z can reach. Think of it as a line that extends to forever, and if a poly is behind it, it can't be seen

Since vertex(0).z is now the highest z, if that's not visible no point is. Anyway now we go into the actual z-clipping.

Just to give you a picture of what's going on, draw a triangle on a paper. This is your poly top-down. Draw a horizontal line(the z clip plane) that removes two points from the poly. If you did it right, you'll notice all that needs to be done is make the two edges to intersect the z-clip plane. Now try the same thing, but this time make the z-clip plane remove only one vertex. You'll see to get the visible poly you'll need to add an extra vertex, resulting in a 4-sided poly.

Since clipping when 2 points are invisible is easier, I'll show you that first.

If vertex(1).z < zclipplane AND vertex(2).z < zclipplane then 'start off processing the first edge.... dx = vertex(1).x - vertex(0).x dy = vertex(1).y - vertex(0).y dz = vertex(1).z - vertex(0).z du = vertex(1).u - vertex(0).u 'necessary to recalculate the new texture co-ordinates because otherwise it gets warped dv = vertex(1).v - vertex(0).v 'find the positions the edge intersects the z-clip plane 'zclipplane = vertex(0).z + t * dz rearrange to find t t = (zclipplane - vertex(0).z) / dz 'now find the new x, y, z, u and v co-ordinates vertex(1).x = vertex(0).x + t * dx vertex(1).y = vertex(0).y + t * dy vertex(1).u = vertex(0).u + t * du vertex(1).v = vertex(0).v + t * dv vertex(1).z = zclipplane 'if zclipplane <> vertex(0).z + t * dz there is an error in your code somewhere 'repeat the above line of code, but change the vertex(1) to a vertex(2) end if

There. Now the array vertex contains your perfect z-clipped triangle. But how do we do it when we have one invisible vertex? Well consider the following. Since vertex(2).z is the smallest z value, it follows that if one vertex is invisible, it has to be vertex(2).z . Think about that if it doesn't make sense. Now go back to that diagram you drew of the triangle with one invisible vertex. Label the point with the largest z as 0, 2nd largest as 1, and the smallest as 2. To find the position of the clipped vertices, we must find where the edge vertex(0) to vertex(2) intersects the z-clip plane, which is the first clipped vertex. The 2nd clipped vertex is where the edge vertex(1) to vertex(2) intersects the z-clip plane.

So here's some code for those of us who are lazy...

extravtx = 0 if vertex(2).z < zclipplane then extravtx = 1 'so the code will remember there is now an extra vertex dx = vertex(2).x - vertex(0).x dy = vertex(2).y - vertex(0).y dz = vertex(2).z - vertex(0).z du = vertex(2).u - vertex(0).u dv = vertex(2).v - vertex(0).v t = (zclipplane - vertex(0).z) / dz vertex(3).x = vertex(0).x + t * dx vertex(3).y = vertex(0).y + t * dy vertex(3).z = vertex(0).z + t * dz vertex(3).u = vertex(0).u + t * du vertex(3).v = vertex(0).v + t * dv dx = vertex(2).x - vertex(1).x dy = vertex(2).y - vertex(1).y dz = vertex(2).z - vertex(1).z du = vertex(2).u - vertex(1).u dv = vertex(2).v - vertex(1).v t = (zclipplane - vertex(1).z) / dz vertex(2).x = vertex(1).x + t * dx vertex(2).y = vertex(1).y + t * dy vertex(2).z = vertex(1).z + t * dz vertex(2).u = vertex(1).u + t * du vertex(2).v = vertex(1).v + t * dv end if

Now we have all the points sitting around in our array vertex. How do we go about displaying it on the screen (I assume you can only tmap triangles)?

Well the first triangle would be vertex(0), vertex(1), vertex(2) . Obviously you have to do your 3d to 2d transformations and such....but you take care of that yourself.

Now look at extravtx. If extravtx = 1, we have an extra vertex, which means, we have an extra triangle. Look back to the triangle diagram. It makes sense if I say the 2nd triangle would be vertex(0), vertex(2), vertex(3), right? Well yes right. That's it! A perfectly z-clipped triangle!

What from here.......

This code can be modified to do frustum culling as well, so you don't have to clip the triangle in 2d anymore! I'll leave that for you to figure out.

I got lazy with my coding and didn't bother either. UGL does the 2d-clipping for me.

If you want to contact me about errors, you need help, or whine about this not working, just contact me, Shashi of SBM Productions at theshashiman@gmail.com


Contact Shashi, or download this tutorial: zclip.txt


x.t.r. Graphics Animation Tutorial

Written by Rattrapmax6 (Kevin)

Introduction

Okay, here I will discuss animation in QBasic. This is probably standard stuff, but I've never read any QBasic animation tutorials. I just sat and thought of the best way I could animate something and did it. So I'm just writing this for those who don't won't to ponder and just want to learn (which is much easier). Enough of my typing, let us get to it!

Frames (Multiple Sprites)

Before you can animate, you need frames, or a bunch of sprite of the same thing just in different positions. Right, so lets draw a object to animate...

SCREEN 13 DATA 23,23,23,23,00,00,00,00,00,00,00,00,00,00,00,00,23,23,23,23 DATA 22,22,22,22,00,00,00,00,00,00,00,00,00,00,00,00,22,22,22,22 DATA 21,21,21,21,00,53,53,53,53,53,53,53,53,53,53,00,21,21,21,21 DATA 22,22,22,22,28,55,55,55,55,55,55,55,55,55,55,28,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,28,55,55,55,55,55,55,55,55,55,55,28,21,21,21,21 DATA 22,22,22,22,00,01,01,01,01,01,01,01,01,01,01,00,22,22,22,22 DATA 21,21,21,21,00,00,00,00,00,00,00,00,00,00,00,00,21,21,21,21 DATA 20,20,20,20,00,00,00,00,00,00,00,00,00,00,00,00,20,20,20,20 FOR y = 1 TO 20 FOR x = 1 TO 20 READ z PSET (x, y), z NEXT NEXT DIM sprt1(20 * 20): GET (1, 1)-(20, 20), sprt1

Okay, in QBasic that makes a robot. We need to make an exact copy of this and change the tracks position. We are going to create the effect of rolling tracks. To come up with this, we move the track's treads up one position, or back one, either way the effect will be the same, look at this...

CLS DATA 23,23,23,23,00,00,00,00,00,00,00,00,00,00,00,00,23,23,23,23 DATA 21,21,21,21,00,00,00,00,00,00,00,00,00,00,00,00,21,21,21,21 DATA 22,22,22,22,00,53,53,53,53,53,53,53,53,53,53,00,22,22,22,22 DATA 21,21,21,21,28,55,55,55,55,55,55,55,55,55,55,28,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,28,55,55,55,55,55,55,55,55,55,55,28,22,22,22,22 DATA 21,21,21,21,00,01,01,01,01,01,01,01,01,01,01,00,21,21,21,21 DATA 22,22,22,22,00,00,00,00,00,00,00,00,00,00,00,00,22,22,22,22 DATA 20,20,20,20,00,00,00,00,00,00,00,00,00,00,00,00,20,20,20,20 FOR y = 1 TO 20 FOR x = 1 TO 20 READ z PSET (x, y), z NEXT NEXT DIM sprt2(20 * 20): GET (1, 1)-(20, 20), sprt2

Animation:

All right, we have two frames ready for animation. We now need to make a master loop and a control loop inside of that one. Sound confusing? Its really easier than it sounds, take a look...

DO ' Master LOOP FOR i = 1 TO 10 'Control LOOP WAIT &H3DA, 8 'Keeps it clean.. FOR a = 1 TO 1000: NEXT 'Controls speed.. NEXT LOOP UNTIL INKEY$ = CHR$(27) 'Ends LOOP on Keypress ..

Now how to use the controll loop to controll the animation. The FOR.. NEXT loop cycles 10 times. We will use this to change the pictures every 5 cycles...

IF i <= 5 THEN PUT (160, 100), sprt1, PSET 'First frame on LOOP 1 - 5 IF i > 5 THEN PUT (160, 100), sprt2, PSET 'Second frame on LOOP 6 - 10

Notice the: "IF i <= 5". "i" is the loop number created by the FOR: "FOR i = 1 TO 10".

Now with: "IF i <=5" on the first five LOOPs PUTs the first frame. And the same with: "IF i > 5" PUTs the second frame on the last five LOOPs.

You can use any number of LOOPs. If you want faster animations, you could use: "FOR i = 1 TO 6" and cycle every 3 LOOPs. Make sure the control LOOPs can divide by two, this way you can PUT the different frames for the equal amount of time. And if you wanted three frames, the control LOOP needs to divide by three and so on... For this tutorial, I’ll leave with this working code.

SCREEN 13 DATA 23,23,23,23,00,00,00,00,00,00,00,00,00,00,00,00,23,23,23,23 DATA 22,22,22,22,00,00,00,00,00,00,00,00,00,00,00,00,22,22,22,22 DATA 21,21,21,21,00,53,53,53,53,53,53,53,53,53,53,00,21,21,21,21 DATA 22,22,22,22,28,55,55,55,55,55,55,55,55,55,55,28,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,28,55,55,55,55,55,55,55,55,55,55,28,21,21,21,21 DATA 22,22,22,22,00,01,01,01,01,01,01,01,01,01,01,00,22,22,22,22 DATA 21,21,21,21,00,00,00,00,00,00,00,00,00,00,00,00,21,21,21,21 DATA 20,20,20,20,00,00,00,00,00,00,00,00,00,00,00,00,20,20,20,20 FOR y = 1 TO 20 FOR x = 1 TO 20 READ z PSET (x, y), z NEXT NEXT DIM sprt1(20 * 20): GET (1, 1)-(20, 20), sprt1 CLS DATA 23,23,23,23,00,00,00,00,00,00,00,00,00,00,00,00,23,23,23,23 DATA 21,21,21,21,00,00,00,00,00,00,00,00,00,00,00,00,21,21,21,21 DATA 22,22,22,22,00,53,53,53,53,53,53,53,53,53,53,00,22,22,22,22 DATA 21,21,21,21,28,55,55,55,55,55,55,55,55,55,55,28,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,00,55,55,55,55,55,55,55,55,55,55,00,22,22,22,22 DATA 21,21,21,21,00,55,55,55,55,55,55,55,55,55,55,00,21,21,21,21 DATA 22,22,22,22,28,55,55,55,55,55,55,55,55,55,55,28,22,22,22,22 DATA 21,21,21,21,00,01,01,01,01,01,01,01,01,01,01,00,21,21,21,21 DATA 22,22,22,22,00,00,00,00,00,00,00,00,00,00,00,00,22,22,22,22 DATA 20,20,20,20,00,00,00,00,00,00,00,00,00,00,00,00,20,20,20,20 FOR y = 1 TO 20 FOR x = 1 TO 20 READ z PSET (x, y), z NEXT NEXT DIM sprt2(20 * 20): GET (1, 1)-(20, 20), sprt2 CLS DO ' Master LOOP FOR i = 1 TO 10 'Control LOOP WAIT &H3DA, 8 'Keeps it clean.. IF i <= 5 THEN PUT (160, 100), sprt1, PSET 'First frame on LOOP 1 - 5 IF i > 5 THEN PUT (160, 100), sprt2, PSET 'Second frame on LOOP 6 - 10 FOR a = 1 TO 1000: NEXT 'Controls speed.. NEXT LOOP UNTIL INKEY$ = CHR$(27) 'Ends LOOP on Keypress ..

Hay! The tracks move!! I'll cover creating animation only when you move, and also how to move the animation in another tutorial. This way you can practice on this alittle, and I'll have something to submit for Pete's QB Express next month....

Have fun making animation, and until next time, happy animating!!!

Contact Me: Rattrapmax6@aol.com

Webpage: http://members.aol.com/rattrapmax6/qbfiles/qbsite.html

-Kevin (x.t.r.GRAPHICS)


Download this tutorial in MS Word DOC format.


GUI Programming In FreeBASIC: Part II

Written by Nekrophidius

In the last tutorial, I demonstrated how to create a window and add some buttons. Now, I'm going to expand on the original tutorial and add more fun stuff. :)

Keep in mind that my tutorials are not intended to be completely cut-n-paste, and that they are intended to point you in the right direction rather than just give all the answers away. :)

*Adding An Editbox*

An editbox is a control that allows you to enter text. You see them all the time in Windows applications for things like login screens, search dialogs, even Notepad itself is just an editbox. At the level we're working at, there is a vast number of styles we can create the box with. Here's one example:

edithWnd1 = CreateWindowEx(0, "EDIT", "EDIT Control", WS_VISIBLE Or WS_CHILD Or ES_MULTILINE OR ES_AUTOHSCROLL OR ES_AUTOVSCROLL OR WS_VSCROLL OR WS_HSCROLL OR ES_LEFT Or ES_WANTRETURN, 250, 30, 200, 80, hwnd, null, hInstance, null)

Quite a selection of styles, no? :) Most of them shouldn't need explaining. A few, however, might be worth looking at closer.

In the example code, "EDIT Control" is the default text that shows up in the control when it's created. Also, this by itself is, again, going to look rather ugly, so perhaps you'd like to set a font here too?

SendMessage (edithWnd1, WM_SETFONT, GetStockObject(DEFAULT_GUI_FONT),0)

Use this SendMessage technique whenever you create controls if you don't want them to use the ugly system font.

*Expanding On The Button Object*

Our versatile button can be used for more than just a pushbutton. The Button window style is also used to create radio buttons and checkboxes.

chkhWnd = CreateWindowEx(0, "BUTTON", "Checkbox!", BS_NOTIFY Or BS_AUTOCHECKBOX Or WS_VISIBLE Or WS_CHILD Or WS_TABSTOP Or WS_GROUP, 30, 0, 200, 17, hwnd, null, hInstance, null)

This creates a checkbox. This uses a few new styles we've not seen yet, but the most important one is BS_AUTOCHECKBOX. What this style does is create the checkbox as a two-state checkbox that automatically switches states when clicked (if this isn't used, you have to change its state manually).

radiohWnd(0) = CreateWindowEx(0, "BUTTON", "Radio 1", BS_AUTORADIOBUTTON Or WS_VISIBLE Or WS_CHILD, 230, 0, 100, 17, hwnd, null, hInstance, null) radiohWnd(1) = CreateWindowEx(0, "BUTTON", "Radio 2", BS_AUTORADIOBUTTON Or WS_VISIBLE Or WS_CHILD, 330, 0, 100, 17, hwnd, null, hInstance, null) radiohWnd(2) = CreateWindowEx(0, "BUTTON", "Radio 3", BS_AUTORADIOBUTTON Or WS_VISIBLE Or WS_CHILD, 430, 0, 100, 17, hwnd, null, hInstance, null) radiohWnd(3) = CreateWindowEx(0, "BUTTON", "Radio 4", BS_AUTORADIOBUTTON Or WS_VISIBLE Or WS_CHILD, 530, 0, 100, 17, hwnd, null, hInstance, null)

Look! Control arrays! :) What this does is create four radio buttons. Like BS_AUTOCHECKBOX, BS_AUTORADIOBUTTON tells the controls to automatically switch states so we don't have to do it manually.

As with any Button, WM_COMMAND is used to handle these controls.

*Adding Menus To The Window*

It is difficult to think of a GUI-based program that doesn't use menus in one form or another. There are two ways of using menus: through resources and through direct API calls. Well, I'm going to show you the working man's version: using API calls.

You'll need some globals for this again, but I'll let you figure out what they should be from the code you're about to see. :)

hMenu = CreateMenu

This is the heart of the menu-making process. Without using CreateMenu, you can't have any menus, period. Now you have a menu handle...time to add actual menus to it.

hMenuSub(0) = CreatePopupMenu hMenuSub(1) = CreatePopupMenu hMenuSub(2) = CreatePopupMenu hMenuSub(3) = CreatePopupMenu

This will create four popup menu handles to which you can menu definitions to. We'll use the first three right away, but the fourth will be used for a special purpose later on.

InsertMenu hMenu, 0, MF_BYPOSITION Or MF_POPUP Or MF_STRING, hMenuSub(0), ByVal "Menu 1" InsertMenu hMenu, 1, MF_BYPOSITION Or MF_POPUP Or MF_STRING, hMenuSub(1), ByVal "Menu 2" InsertMenu hMenu, 2, MF_MENUBREAK Or MF_BYPOSITION Or MF_POPUP Or MF_STRING, hMenuSub(2), ByVal "Menu 3"

Now here's where the real fun begins. This creates three top-level menus in the menu bar of the window. Note the additional style in the third line, MF_MENUBREAK. This splits the menu bar, allowing that third menu to appear as a second line in the menu. This is something you *never* see in VB! :)

Now that we have our top-level menus, we can add some actual dropdown menus.

AppendMenu hMenuSub(0), MF_STRING, &H11, Byval "MenuSub 1.1" AppendMenu hMenuSub(0), MF_STRING, &H12, Byval "MenuSub 1.2" AppendMenu hMenuSub(0), MF_STRING, &H13, Byval "MenuSub 1.3" InsertMenu hMenuSub(0), 3, MF_BYPOSITION Or MF_POPUP Or MF_STRING, hMenuSub(3), ByVal "Nested Menu 1" AppendMenu hMenuSub(3), MF_STRING, &H31, Byval "Nested SubMenu 1" AppendMenu hMenuSub(3), MF_STRING, &H32, Byval "Nested SubMenu 2" AppendMenu hMenuSub(3), MF_STRING, &H33, Byval "Nested SubMenu 3"

This creates a dropdown menu on the first top-level menu handle. What's more is that it also creates a submenu using that fourth popup menu handle we defined earlier.

AppendMenu hMenuSub(1), MF_STRING, &H21, Byval "MenuSub 2.1" AppendMenu hMenuSub(1), MF_STRING, &H22, Byval "MenuSub 2.2" AppendMenu hMenuSub(1), MF_STRING, &H23, Byval "MenuSub 2.3"

This is a pretty standard menu, nothing special needs explaining here.

AppendMenu hMenuSub(2), MF_STRING, &H31, Byval "MenuSub 3.1" AppendMenu hMenuSub(2), MF_STRING Or MF_MENUBREAK, &H32, Byval "MenuSub 3.2" AppendMenu hMenuSub(2), MF_STRING Or MF_MENUBARBREAK, &H33, Byval "MenuSub 3.3" AppendMenu hMenuSub(2), MF_STRING, &H34, Byval "MenuSub 3.4" AppendMenu hMenuSub(2), MF_STRING, &H35, Byval "MenuSub 3.5" AppendMenu hMenuSub(2), MF_STRING, &H36, Byval "MenuSub 3.6" AppendMenu hMenuSub(2), MF_STRING, &H37, Byval "MenuSub 3.7"

Here's another interesting usage of menu styles. You saw MF_MENUBREAK earlier on the top-level menu, but here in a submenu, what this does is split the menu horizontally. All following menu items will be displayed under this menu item, Also, we've got MF_MENUBARBREAK. This works the same as MF_MENUBREAK except it adds a vertical line, visually seperating the menu items. Again, all items following this are displayed under it. Again also, this is something you never see in VB.

SetMenu hWnd, hMenu

Okay, we've had enough menu fun for now. This command sets the menu to its parent, which will be the window we've created.

DrawMenuBar hWnd

This final step is necessary to actually show this menu.

There are a few notifications involved with menus, but the one we want to be concerned with primarily is WM_COMMAND. When a menu item is fired, lparam will be 0. So where do we get info on which menu item we want? In wparam, of course! The low word of wparam will contain the identifier of the menu item fired. Remember that small code snippet at the end of the last tutorial? Use the GetLowParam function with wparam to return the identifier of the menu fired. When the menus were created, we used a value at the third argument of AppendMenu to specify its identifier. So all you do is compare the low word of wparam to this identifier to determine which menu item was fired.

Other interesting notifications we can look at are WM_INITMENUPOPUP, which is fired when a popup menu "pops up", WM_UNINITMENUPOPUP, which is fired when a popup menu is closed, and WM_MENUSELECT, which unlike WM_COMMAND, returns the handle of the menu in lparam but otherwise functions in a similar (although a bit more complex) manner. WM_MENUSELECT is what you'll want to use when your window contains a lot of controls and you want to keep things cleaner and neater in your WndProc. :)

*The End...For Now*

Well, I hope this sheds a little more light on the wonderful (*cough*) world of GUI coding at the API level in Windows. As before, if something doesn't make sense or you would like to ask a question, feel free to contact me. I'm not hard to find. :D And I'll continue this tutorial series next month, exclusively for QB Express. :)


Contact Nekrophidius, or visit one of his many programming websites:
The Basic Network, V Planet!, Lost socK Software or Nek's FreeBasic Page!


SDL Basics With FreeBasic - Tutorial 1

Written by BastetFurry

This and the following tutorial were originally posted on the QBasic News forums. Bastetfurry submitted these to QB Express on the advice of QBNews forum readers and here they are. Enjoy!

In this tutorial you will learn to set up SDL and get an image on the screen, pretty cool, uh?

Ok, it is just to teach you the basics of SDL.

So, have a look at this little piece of code:

'$include: "SDL\SDL.bi" '$include: "SDL\SDL_image.bi" ' Surfaces are the A and O of SDL. ' You place your backgrounds, your sprites and everything else that has ' something to do with graphics inside a surface. ' This will hold the screen dim shared video as SDL_Surface ptr ' This will hold our picture dim shared temppic as SDL_Surface ptr ' Here goes the event holder dim event as SDL_Event ' We initiasize SDL and we only need video. If this tells me anything but zero ' then we can not continiue if SDL_Init(SDL_INIT_VIDEO) <> 0 then print "FATAL: Couldnt init SDL" end 1 end if ' We set up the display mode. We wont do fullscreen, if you like then OR the ' options with SDL_FULLSCREEN to get it. ' SDL_HWSURFACE means that this surface is hold in video ram. ' If you want it to be in system ram then exchange SDL_HWSURFACE with ' SDL_SWSURFACE ' SDL_DOUBLEBUF tells SDL to create two pages. video = SDL_SetVideoMode (800, 600, 24, SDL_HWSURFACE OR SDL_DOUBLEBUF) ' If the surface holds nothing then the display is not created, then get out of ' here. if video = NULL then print "FATAL: Couldnt init SDL with vidmode 800x600x24" end 2 end if ' Now we load the Picture to be displayed into system memory ' You can load bmp, pnm, xpm, xcf, pcx, gif, jpg, tif, png and lbm ' I stick with png because gif is patented and just 256 colors thick and the ' others are just too bloated or destroy information in the picture. temppic = IMG_Load("testpic.png") ' If this is empty then something went wrong if temppic = 0 then print "Could not load file: "; picfile$ end 3 end if ' We blit the image to the screen. ' SDL_BlutSurface has the parameters ' (start,startcoordinates,destination, destinationcoordinates) ' Where coordinates is a simple SDL_Rect structure. SDL_BlitSurface(temppic,NULL,video,NULL) ' With this command we flip the video ram locations so that our painting gets ' visible. SDL_Flip(video) ' We dont need temppic anymore so get rid of it SDL_FreeSurface(temppic) do ' We grab the newest event from the event stack. ' I havent tryed it, but AFAIK you can even grab Win32 events like WM_CLOSE ' this way ;) SDL_PollEvent(@event) ' We just want the type of the event select case event.type ' Has a key been pressed? case SDL_KEYDOWN: exit do ' Has a mousebutton been pressed? case SDL_MOUSEDOWN: exit do ' In both cases we just get out of here end select loop ' And as we dont asume that the compiler calls it, old C habbid ;), we assure ' that it is done and SDL gets deinitialised SDL_Quit()

In the next issue I will tell you how to move objects and achive transparency.

So Long, The Werelion!


Contact Bastetfurry, or view the original tutorial post.


SDL, FreeBASIC, Transparency, Keyboard and Other Suspects - Tutorial 2

Written by Bastetfurry

In this issue I will tell you how to add transparency and how to move your objects around.

For this we need a graphic, preferable 32x32 with 24 bit colors.

Rip somewhere or make your own, it wont matter.

Now, get one information, what will be the transparency.

I prefer "Magic Pink" which is 255,0,255 , as long as you know which color number your transparency color has it will work.



Now, you load your image/sprite/whatever with IMG_Load as usual and after that you just do the following:

SDL_SetColorKey(YourSpriteSurface, SDL_SRCCOLORKEY, SDL_MapRGB(YourSpriteSurface->format, 255, 0, 255))

The last three numbers represent your transparency color.

Now everytime you blit your image you will get a nice image with transparent areas as SDL now does the rest for you, cool eh?



For exercise, add a small sprite to your first SDL programm that has transparency.



So, it should look somewhat like this:

'$include: "SDL\SDL.bi" '$include: "SDL\SDL_image.bi" ' This will hold the screen dim shared video as SDL_Surface ptr ' This will hold our picture dim shared temppic as SDL_Surface ptr ''' NEW CODE STARTS HERE! ' This will hold our sprite dim shared pic as SDL_Surface ptr ' This will be explained later, its for telling SDL where to draw ;) dim shared rect as SDL_Rect ''' NEW CODE STOPS HERE! ' Here goes the event holder dim event as SDL_Event ' We initiasize SDL and we only need video. If this tells me anything but zero ' then we can not continiue if SDL_Init(SDL_INIT_VIDEO) <> 0 then print "FATAL: Couldnt init SDL" end 1 end if ' We set up the display mode. video = SDL_SetVideoMode (800, 600, 24, SDL_HWSURFACE OR SDL_DOUBLEBUF) ' If the surface holds nothing then the display is not created, then get out of ' here. if video = NULL then print "FATAL: Couldnt init SDL with vidmode 800x600x24" end 2 end if ' Now we load the Picture temppic = IMG_Load("testpic.png") ' If this is empty then something went wrong if temppic = 0 then print "Could not load file: testpic.png" end 3 end if ''' NEW CODE STARTS HERE! 'We load our sprite into memory pic = IMG_Load("testsprite.png") ' If this is empty then something went wrong if pic = 0 then print "Could not load file: testsprite.png" end 3 end if ' Now we set the transparency SDL_SetColorKey(pic, SDL_SRCCOLORKEY, SDL_MapRGB(pic->format, 255, 0, 255)) ''' NEW CODE STOPS HERE! ' We blit the image to the screen. SDL_BlitSurface(temppic,NULL,video,NULL) ''' NEW CODE STARTS HERE! ' This will draw our sprite with transparency on the coordinates stated rect.x = 50 rect.y = 150 ' SDL_Rect needs to be passed as a pointer! You dont need to fully understand ' what a pointer is, just do it otherwise it wont work ;) SDL_BlitSurface(temppic,NULL,video,@rect) ''' NEW CODE STOPS HERE! ' We flip SDL_Flip(video) ' We dont need temppic and pic anymore so get rid of it SDL_FreeSurface(temppic) SDL_FreeSurface(pic) do ' We grab the newest event from the event stack. SDL_PollEvent(@event) ' We just want the type of the event select case event.type ' Has a key been pressed? case SDL_KEYDOWN: exit do ' Has a mousebutton been pressed? case SDL_MOUSEDOWN: exit do ' In both cases we just get out of here end select loop ' We have finished SDL_Quit()

Ok, lets get on with that mysterious SDL_Rect...

This dude is a structure that holds 4 variables.

x and y for upper left corner of drawing and we have w for widht and h for height. The last two are not interesting for the pasting part, but when you use one big image for, for example, all enemy spaceships, you can select what portion of your image is blited to the screen.



But now we go on on using that dude for moving something around the screen.

'$include: "SDL\SDL.bi" '$include: "SDL\SDL_image.bi" declare sub updatescreen() ' This will hold the keyboard data dim keys as Uint8 ptr ' We need to know if we need to redraw the screen dim shared redraw% ' This will hold the screen dim shared video as SDL_Surface ptr ' This will hold our picture dim shared temppic as SDL_Surface ptr ' This will hold our sprite dim shared pic as SDL_Surface ptr ' This will be explained later, its for telling SDL where to draw ;) dim shared rect as SDL_Rect ' Here goes the event holder dim event as SDL_Event ' We initiasize SDL and we only need video. If this tells me anything but zero ' then we can not continiue if SDL_Init(SDL_INIT_VIDEO) <> 0 then print "FATAL: Couldnt init SDL" end 1 end if ' We set up the display mode. video = SDL_SetVideoMode (800, 600, 24, SDL_HWSURFACE OR SDL_DOUBLEBUF) ' If the surface holds nothing then the display is not created, then get out of ' here. if video = NULL then print "FATAL: Couldnt init SDL with vidmode 800x600x24" end 2 end if ' Now we load the Picture temppic = IMG_Load("testpic.png") ' If this is empty then something went wrong if temppic = 0 then print "Could not load file: testpic.png" end 3 end if 'We load our sprite into memory pic = IMG_Load("testsprite.png") ' If this is empty then something went wrong if pic = 0 then print "Could not load file: testsprite.png" end 3 end if ' Now we set the transparency SDL_SetColorKey(pic, SDL_SRCCOLORKEY, SDL_MapRGB(pic->format, 255, 0, 255)) do ' We grab the newest event from the event stack. SDL_PollEvent(@event) ' We just want the type of the event select case event.type ' Has a key been pressed? case SDL_KEYDOWN: ''' NEW CODE STARTS HERE ' After this redraw%=1 ' Grab the state of the keyboard keys = SDL_GetKeyState(NULL) ' Test all interesting possibilities with boundary check. ' It wont matter if you draw outside the screen, SDL clips for you if keys[SDLK_UP] and rect.y > 0 then rect.y = rect.y - 1 if keys[SDLK_DOWN] and rect.y < 568 then rect.y = rect.y + 1 if keys[SDLK_LEFT] and rect.x > 0 then rect.x = rect.x - 1 if keys[SDLK_RIGHT] and rect.x < 768 then rect.x = rect.x + 1 if keys[SDLK_ESCAPE] then exit do ''' NEW CODE STOPS HERE ' Has a mousebutton been pressed? case SDL_MOUSEDOWN: print "MB pressed" ' In both cases we just get out of here end select if redraw% = 1 then redraw% = 0 updatescreen() end if loop ' We have finished SDL_Quit() ''' NEW CODE STARTS HERE ' It is a good habid not coding everything into the message loop ' This sub updates the screen sub updatescreen() ' Nowadays its normal updating the whole screen as the PC has no universal ' scrolling routines, neither does it come with native sprite support. ' Besides, with SDL even an old 486 can maintain 25-30 fps ' We blit the image to the screen. SDL_BlitSurface(temppic,NULL,video,NULL) ' We blit the sprite to the screen. SDL_BlitSurface(temppic,NULL,video,@rect) ' We flip SDL_Flip(video) end sub ''' NEW CODE STOPS HERE

That's it, this is what SDL mostly is about.

Now, for exercice, have a try and make a simple labyrinth game or a simple space shooter with SDL.

The next tutorial will be about something YOU decide, the only thing I won't do is SDL+OpenGL because I dont know OGL.

And I would be very happy if someone could proofread my bad english.

So Long, The Werelion!


Contact Bastetfurry, or view the original tutorial post.


16 Megs .EXE files using overlays

Written by Na Than Assh Antti (Na_th_an)

This is a tutorial that Na_th_an wrote a while ago for his BASIC compilers website, but when the site went down, so did the tutorial. It's a quite useful tutorial that really deserves to be read (plus some more recognition than it was getting before), so I've decided to reprint it in QB Express.

-Pete

Intro

As soon as a QB programmer aims for a big project, he or she will (most likely) be trapped in the deep and dark well of memory problems. Sometimes your program refuses too compile no matter how many modules you split it into, sometimes it will compile but will do nasty things when executed, sometimes it will throw a "out of memory" error, and I can keep it going forever.

This is not just a QB issue (although it is easier to get such kind of problems with QB than with another similar compiler), but a 16-bits MS-DOS environment issue. You have 640 Kb of conventional memory to work with is real mode (QB, Turbo C++, and many other old compilers work in real mode), where you have to fit static, dynamic and code data. Far too little.

Back in the days, EMS and then XMS were introduced to have more memory to work with. This solves the problem to a point, 'cause you can only store data on EMS/XMS. No way to pass a program counter to EMS or XMS, so no way to actually execute a program from that zone. Sometimes you need more code. Many people just resignate and split their projects into several EXEs, and have to invent all sorts of tricks to have the data available from one to the next.

To solve that, Overlays were introduced. Overlays are just a pack of modules (OBJ files, to aid in understanding) that are kept on disk until they are needed. Overlaid programs contain a main module which is always in memory. When a function is called, a little control program checks if it is loaded or not. If it is not, it loads the overlay it is in from disk and calls the function. That way you can have much bigger programs.

So, how is it done?

Don't worry, you don't have to call special functions, or code in an odd way. I feared those things until I met Jonathan Simpson and he pointed me to the correct document. The version of LINK.EXE included in PDS 7.00 or later does the work for you. You only have to tell LINK which object modules are on which overlays. Sadly, this can't be done from the IDE as far as I know, but not everything has to be a piece of cake. You have to compile your BAS file to OBJs using BC.EXE, and then run LINK.EXE to link the OBJs. The syntax for LINK is very simple. For example, say that you have seven object files (OBJs) named A.OBJ, B.OBJ, ... I.OBJ, and you want to organize them in three overlays. You just have to type in (provided you have your OBJs already created):

LINK A+(B+C)+(E+F)+G+(I)

The above command will create an EXE file but it will be a special, overlaid file. On it, object modules A and G will make the main portion which is always loaded in memory. B and C will make a overlay, E and F will make another and I will make another one. Note how object modules enclosed in parentheses get together inside an overlay, and how modules that are not enclosed in parentheses will be in the main section.

The program entry point (main section of your code) must be in the main section of your EXE file (not in a overlay). In execution, if a function in B.OBJ is needed, the overlay containing B.OBJ (which also contains C.OBJ) is loaded from disk, and the function is called. Imagine than then you need a function placed in C.OBJ now: no prob, the overlay is already loaded and the function will be called. Now you need some stuff at F.OBJ: well, no prob, B+C is unloaded and E+F is loaded from disk, then the function is called.

As you see, you don't have to do anything. Overlays are loaded and unloaded automaticly, so you don't have to change a line of code, just organize your OBJs intelligently on overlays... See next point.

Organizing stuff

You probably are thinking on this already: loading and unloading (specially the former) overlays takes time. Yeah, it does. And a lot of time compared to the time that is spent to call a function. You won't notice it when the load is outside a loop, but if it is inside a critical loop you will.

Overlays were a "patch solution" to code size problems. Like every other patch solution, it has lots of downsides. But luckily, these downsides can be ignored if we do things intelligently.

Most times, your program can be "sequentialized", that is, you can see how not all the SUBs and FUNCTIONs are used always, but that there are some kind of "stages". For example, in a game, you have a menu which calls to "options", "play" and "instructions". The "Options" SUB calls its own SUBs and FUNCTIONs that have nothing to do with those functions called by the "play" SUB, same for the "instructions" SUB. I mean that you, for example, are calling "DoScroll" from your "play" SUB constantly, but this SUB won't be ever called from the "options" SUB. Now you have a hint on how to organize your stuff: you can have an overlay with the menu system, another with the options stuff, another with the game itself and another one with the instructions.

"Hey, stop it a while", you may say. Yeah, I know, all those SUBs and FUNCTIONs that we have taken appart make use of the soundsystem and the graphics library. Easy: put the most commonly used stuff in your main section. That way they will always be loaded. Imagine how killer it were to place the soundsystem in an overlay and the game in another: everytime that a sound had to be played from the game module, it would have to be unloaded and the sound overlay would have to be loaded... No way. :)

Another good division can be made in RPG games: Stuff your map engine in an overlay (along with the scripting engine and everything) and the battle engine in another. I've seen so many games that use different EXEs for the map engine and the battle engine. I always found that dirty. Now this is no longer needed :) and you have all your variables still on memory!

As you see, if you organize modules intelligently, the overlays system has no drawbacks. In most cases, even if you don't need overlaying 'cause your code is small enough, it can be better to overlay some parts of your program that are not used in critical loops so you are saving memory for data in conventional memory. Plus, with modern computers and operating systems, the time needed to load the overlay from disk is unnoticeable. Furthermore, if you are using Windows all disk accesses are cached so most likely your overlay to be loaded is somewhere in memory, so loading it is even faster. There is an even better feature: if the EMS driver is loaded, overlays are copied to EMS as well when they are loaded, and then they are retrieved from memory next time they need to be used.

Stop! There are some restrictions

Yeah, that's a bummer, but as I said before: nothing is perfect.

A lil' tip

Create a .BAT file to compile and link automaticly. Study the LINK.EXE syntax so you can use .LIB libraries and pass parameters (in the above command LINK is only passed info about which OBJs will be linked, so it will prompt interactively for the missing info; you have to add these parameters to have LINK.EXE working automaticly).

Aknowledgements

Thanks to Jonathan Simpson for pointing me in the correct direction, concretely to BotTheMad's article at Tek-Tips Forums.


Contact Na_th_an or visit his website.


FreeBasic Pointers Tutorial

Written by VonGodric

About this tutorial

This tutorial is meant to be as a guide to FreeBasi'c pointers world for beginners or who just wish some information about them and their support in FreeBasic. This tutorial will cover several types of pointers and their notations, also breafly about linked lists and their types and pointers to functions/subs. As well as pointers to pointers. Als should be noted that writing this tutorial I used fbc compiler 0.11 and becouse of that some of the stuff won't work on older versions!

What are pointers?

To understand what are pointers, we need to understand what variables are. Variables are references to a memory location in RAM where you can write or read data. So thus, they store some data and have an address in memory. In basic definition Pointers are variables that store address of another variable. That's where the name comes from Pointer -points to something.

Pointers in FreeBASIC

FreeBASIC unlike QBasic and many other BASIC dialects has full support for them. FB have them to following language structures:

The notation is very similar to C with exception of @ instead of & to take addresses. (for obvious reasons -it would conflict with { &h | &b | &o } numbering systems.) So let's get to it.

Starting with pointers...

Here's our first small example:

dim i as integer print @i

When you run it -it will print out some strange number, further more, every time you run this program, it may show you different number, and it is most unlikely to get the same number after restart. When I ran it the number was: 4218880

This number is the memory address of the variable i. You can experiment with this a little -try different variable types for example. However be noted: that misusing pointers may lead to program crash, in worse situations even system crash!

Creating pointers is very similar to declaring a variable with dim: Dim name Type PTR|POINTER it doesn't matter do you use ptr or pointer, both are the same thing. so here's another litte example:

option explicit dim i as integer dim ip as integer ptr ip = @i print @i print ip

As you will see, both number are the same -however, You may notice that we pass the address of the variable i to the pointer ip. and ip used as is, is just a variable. You can also get the address of the pointer ip itself with @ip -and it will be different, because every variable has a unique address (it is possible to have variables with the same address however with Union's)

Now let's do some actual use of pointers:

option explicit dim i as integer dim ip as integer ptr i = 10 ip=@i print *ip 'Print out the value to what pointer points *ip =20 'Assign value to variable that pointer points print i

The outcome will be 10 and 20 accordingly. The * will give the value of the variable that our pointer points to, or write to the value. Now you may have a question, what are they good for? Well great many things, pointers may speed-up or/and cut down your program in size. They'r most common use is however is in linked lists(will be looking at them shortly) and allocating memory from the heap (we'll discuss about that too). So here's one more example:

option explicit dim i as integer dim m as integer dim ip as integer ptr ip = @i *ip = 10 : m = 25 print *ip * m print sqr(*ip) *ip = *ip -5 print *ip print *ip / m sleep

As you see, pointers can be used just like any normal variables -you can assign values through them, use in calculations, pass as arguments, and mutch more. However word of caution: do NOT mistake *ip with just ip, one is a memory address -and therefore holds completely different value -and the other one the value of the variable the pointer points to. So therefore doing ip = ip * m for example will change the address it points to -and most probably will crash your program when you try to use it as pointer again: *ip = 100.

Pointers and arrays

Hopefully you understood previous stuff -if not try experimenting. Just as pointers may be used with variables, they can also be used with arrays. First a small example, then we'll analize it:

option explicit 'Define array and pointer dim array(10) as integer dim ap as integer ptr dim i as integer 'Fill array with numbers for i = 0 to 10 array(i) = i next 'Pass the address of the first element ap=@array(0) 'And print it out for i = 0 to 10 print *(ap+i) next sleep

It will print out numbers from 0 to 10. So what is going on in there? We pass the address of the first array element to the pointer (ap=@array(0)), and then we go through the loop from 0 to 10 and print out. The notation *(ap + i) means: we will print out to what points the value that is in the parenthesis. You may however wonder why it prints out the right numbers? Shouldn't it screw the values -meaning that pointer always points to one byte in memory, but Integer is 4 byte? The FreeBasic compiler knows the size to what the pointer points, and meaning + 2 means actually to step 2 integer sizes forward.

Why is this useful: You may link what ever integer array (or of any other type you have specified) to one pointer and use it, without having to know exactly what is in it. Here is the same thing as above with a bit different notation:

option explicit 'Define array and pointer dim array(10) as integer dim ap as integer ptr dim i as integer 'Fill array with numbers for i = 0 to 10 array(i) = i next 'Pass the address of the first element ap=@array(0) 'And print it out for i = 0 to 10 print ap[i] next sleep

Does the same thing -only difference now is instead of *(ap + i) ap[i] This is just a shorter notation and is a bit cleaner. In this case you don't need (in fact can't) use * in front of the pointer -that's because of the [ and ]. When these are used, compiler automatically knows that this is a pointer. ap[indx] = smth is also valid.

because of greater complexity of multidimensional arrays using pointers in FreeBasic, we'll skip them for now.

Pointers and UDT's

Like to arrays, you can have pointers to user defined types too. Here's for starter another example:

type mytype i as integer s as single z as string end type dim t as mytype dim up as mytype ptr t.i = 10 t.s = 17.87 t.z = "UDT ptr test" up=@t print up->i print up->s print up->z sleep

As you see, pointers with UDT's is very simle, first you define a ptr of the udt type and then take the address of it with @t and for getting the right field we use -> and field name. Note that * is not needed, because of -> what says already that this is a pointer. Assigning values through pointers is ptr->field = value. Like with arrays -different notations can be used:

'variant 2 print *(up).i print *(up).s print *(up).z 'variant 3 print up[0].i print up[0].s print up[0].z

This second and third style, as you see is almost like arrays with *(ptr+idx), infact, you can use pointers with arrays of UDT's too. And notation is almost same:

type mytype i as integer s as single z as string end type dim t(5) as mytype dim up as mytype ptr t(3).i = 10 t(3).s = 17.87 t(3).z = "UDT ptr test" up=@t(0) print *(up+3).i print *(up+3).s print *(up+3).z print up[3].i print up[3].s print up[3].z sleep

As you see, all calculations are done for you, the index 3 will give the correct answer and you can choose from several styles and decide what suits you best.

Arrays/UDT's outside of DIM

When you use DIM -you use the memory that has been previously allocated for your running program by the OS (in FB the default is 1MB -however for more see the commandline options of fb), but what if you want more? One way to archive this would be to increase stack size allocated for your program -but if you want to have dynamically allocatable memory (games/programs often need that) -you are still stuck to that problem! Solution is to allocate memory from the system heap -let's just say that it's the rest of the free memory in your computer that is not already used by other applications. To use memory from the heap is more complex and dangerous then with DIM.

Why it's dangerous, is that this is often main source of crashes and errors, you probably have heard of memory leaks? Well you're about to get to know what they are: DIM procedure is controlled by the compiler -so whenever you allocate with it, it get's automatically deallocated once program exits SUB or FUNCTION for example. So memory is freed. However allocating memory from the heap, is not deallocated(freed) after your code has done it's work (exited sub/function or program itself) although modern OS's do free memory for you it is a good practice to not rely on it! Keep in mind a simple rule -once you allocate, next thing you do is make sure it get's deallocated!

Now what has this to do with pointers? Well everything, you get the address to the allocated memory block, so only using pointers can you acces to it. Now before we move on, let's make a simple example:

option explicit type mytype i as integer s as string * 12 end type dim p as mytype ptr p = allocate(len(mytype)) if p = 0 then print "ERROR: Out of memory!" sleep end end if *(p).i = 10 *(p).s = "Hello world!" print p->i print p->s sleep deallocate p

Now let's analyse that. First we created an udt, then dimmed pointer to udt. then we allocated memory for our udt. ALLOCATE allocates memory from the heap. Len(mytype) returns the size in bytes that udt takes. We need to know how mutch memory to allocate. What allocate returns is a pointer to the first byte of the memory stream. And that's all, now we can use it almost like with Dim, but with exception of being able to access it only through pointers. The last thing is to deallocate -it erases(frees) the memory we had allocated.

Warnings!

Now that warnings have been said (reread them) we can move on and see how can we put an arrays to the heap.

option explicit dim i as integer dim p as integer ptr p = callocate(len(integer) * 10) if p = 0 then print "ERROR: Out of memory!" sleep end end if for i=0 to 9 p[i] = i next for i=0 to 9 print *(p+i) next sleep deallocate p

Notice that we allocated memory by multiplying the size of integer by ten, but true indexing ranges from 0 to 9, be aware of this! Placing UDT's to heap is done just the same way, only use len(udt) and if you want to have an array of it, multiply it by array size.

Linked lists

Now that we have understood all previous, let's move on. As you saw pointers can point at UDT's, but they can also be a part of the UDT, furthermore pointer part of the UDT can point to it'own UDT -thus linked lists. All there is about these mysterious things is this that udt's point to other udt's. Let's start with simple example:

'Simple linked list example type linkedlist 'data that list holds i as integer 'points to next node listnext as linkedlist ptr 'pointe to previous node listprev as linkedlist ptr end type 'the head node of the list 'and two for temporary use dim head as linkedlist ptr dim node as linkedlist ptr dim temp as linkedlist ptr for i = 1 to 10 'allocate memory node = callocate(len(linkedlist)) if node = 0 then 'see if allocation was succesful print "ERROR: Out of memory" sleep 'because some initalisations may have 'been successful, we need to deallocate them goto endlinkedlist: end end if node->i = i 'set our data 'point to previously allocated node node->listprev = temp if temp = 0 then 'see if temp is 0 -if is then it is first 'allocation temp = node 'set temp to show current one head = temp 'also set head continue for end if 'set next node of the previous node to be current one temp->listnext = node temp = node 'set this for next run next 'since we save first node as head -we can use it to start reading from the list node = head 'since final node's listnext holds 0, we can use this 'as the condition to terminate when link is over while node 'print out data that node holds print node->i; 'save the current node -for the next demo temp = node 'move to the next one node = node->listnext wend print 'since we saved in previous demo temp to 'be last active node, we can use it node = temp 'Just like listNext of the lastnode is NULL pointer 'so is listPrev of the first noe. So again we can use this as 'terminate condition to make sure we exit the list. while node 'print out data that node holds print node->i; 'instead of next -let's move backwards node = node->listprev wend sleep endlinkedlist: 'again start from the head and move through node = head while node temp = node 'to avoid getting next node from already 'deallocate node, we need to use a temp node = node->listnext deallocate (temp) wend

This should be pretty easy concept to understand -node is one UDT block, that points to previous or/and next node or have NULL pointer meaning the end of the list. Why is this good for? Linked lists are in a way like arrays (you probably notices this by now) but they have several advantages and disadvantages over arrays.

Pros
Linked lists: Arrays:
Each node is seperated unit Fast -since arrays are aligned in memory.
Easy and fast to add/remove/replace nodes with one another Compact -takes less memory
because each node is seperate unit -it doesn't take large memory block with the size of the whole List Lot Easier handling
Same node can be pointed from different lists Are less bug prones
Very dynamic Easy to copy/pass whole arrays (to a file)

Cons
Linked lists: Arrays:
Consume more memory Slow and compilcated remove and insert
Slower in most cases Consume big memory block (sometimes there's enough of free memory, but it is in too small chunks)
Introduce many risks for bugs and memory leaks All pros's of the Linked lists
more complex

These tables should give you some ideas -there's certanly more no doubt but these should give you some idea. Although subject is interesting I will not however get really deep into linked lists here, because only on this subject there have been written entire books and there are many different types of linked lists in various shades and shapes. Some most common ones however:

Pointers and functions/subs

So far We've been through a lot and there's very little left to describe -although it is a matter on what could be possible to write heavy nooks. First We'll look at pointers in the functions/subs argument lists.

Very similar actually to defining any other pointer -you just put a pointer, and pass the pointer or address with @.

sub test (byval i as integer ptr) print *i end sub dim i as integer i=10 test ( @i ) sleep

You may notice here byval argument -it is meant that pointer(value it holds) is passed by value itself and not reference(aka address) to that variable in what value is stored. Let's see here what byref does:

sub test (byref i as integer) i = 10 end sub dim i as integer print i test i print i sleep

Inside function/sub byref passed variable obtain the same address as of the variable that was passed. Functions can also return pointers, in that case you need to do function (args...) as type PTR.

However more interesting part ( and very useful ) is pointers to subs/functions themselves. Yes, it is possible!. Here's small example:

sub sub1 ( i as integer ) print "hello from sub1" print "you passed value: "; i end sub sub sub2 ( i as integer ) print "hello from sub2" print "you passed value: "; i end sub dim test as sub (i as integer = 10) test = @sub1 test ( 6 ) test ( ) test = @sub2 test ( 1001 ) test ( ) sleep

As you can see, different sub's are called -and yes you can set default values on sub/functions pointers too. What is importand in sub/function declarations is that the prototype MUST match the prototype of the function/sub your are using pointers on. You can also pass function/sub pointers inside another function/sub parameter lists as well:

function func2 ( i as integer ) as integer func2 = i * i end function function func1 ( byval tocall as function, byval value as integer ) dim i as function ( i as integer ) as integer i = tocall func1 = i ( value ) end function dim s as function ( byval tocall as function(i as integer), byval value as integer ) as integer s=@func1 print s(@func2, 10) sleep

As you see, using function pointers is almost same, only you must specify all types both the return one and also parameter list. Also as you can see, one pointers value can be given to another.

option explicit dim i as integer dim ip1 as integer ptr dim ip2 as integer ptr ptr ip1 = @i ip2 = @ip1 **ip2 = 157 print i, *ip1, **ip2 print @ip1, *ip2 ip2 = @i *ip2 = 751 print i, *ip2 sleep

Now look at this code -it should be pretty straightforward don't you think? Anyway declaring a pointer that points to another pointer must be declared explicitly as ptr ptr ... with the number of maximum redirections allowed. To point to the target you use * as many times as redirection is involved.

Typeless Pointers

Sometimes we do not really know or need to either, the type of the pointer in our program, let's say like when passing to the function/sub as an argument, we may be dealing with different types in it. For that in FB is ANY ptr. Here's example:

option explicit sub test (byval p as any ptr, byval t as integer) dim i as integer ptr dim b as byte ptr dim s as string ptr dim d as double ptr i = p b = p s = p d = p select case t case 1 print *i case 2 print *b case 3 print *s case 4 print *d end select end sub dim i as integer dim b as byte dim s as string dim d as double i = 10001 b = 127 s = "Hello world!" d = 2005.0208 test @i, 1 test @b, 2 test @s, 3 test @d, 4 sleep

As you see, nothing difficult here either. You may experiment with passing "wrong" numbers for wrong types. It should work except for strings. And that's more or less there is to typeless pointers. Also addresses can be passed without a problem from one pointer to another with different types -let's say from an integer ptr to the byte ptr. This way you can archive sort pointer casting from one type to another.

Conclusion

Well that's pretty mutch it for this tutorial. I hope you liked it and found something useful or new for yourself. One more thing however, throughout this tutorial I used @ symbol to obtain and address of smth, however these functions maybe used as well:

Also I want to thank lillo for reviewing this bag of grammatical bugs. And now farewell and thanks for reading this.

VonGodric


Download this tutorial.
Visit VonGodric's WizGUI site, find out about his FBIde project, or email him at vongodric@hotmail.com!


Final Word

Eleven tutorials. 211KB of text alone. The largest news briefs section yet. I really can't believe how much content there is in this magazine this month. It's absolutely phenomenal. You can't find this quantity of quality content in many professional magazines. And yet, here we are, month after month, putting together a gigantic and completely awesome magazine. Everyone involved deserves a pat on the back. This magazine would not exist without the readers -- who are also the writers.

Anyway, I'm gonna cut this letter short. This issue has been delayed enough, and I don't want to keep it out of your hands any longer than I have to. Besides, I'm extremely tired (putting this magazine together takes hours upon hours of grueling, repetitive work). But in the end it's worth it.

Next month expect a whole lot more of the same great stuff and maybe a few surprises. I'm not going to list off any specific articles here, since I never know what I'm going to get, but I can assure you that whatever ends up in Issue #8 is going to rock. Anyway, I'll see you in March!

Until next time...END.

-Pete


Copyright © Pete Berg and contributors, 2005. All rights reserverd.
This design is based loosely on St.ndard Bea.er by Altherac.