QB Express
Issue #17 ~ January 9, 2006
"A magazine by the QB community, for the QB community!"
In This Issue
Contributors
- Pete (Editor)
- MystikShadows
- Nekrophidius
- Lachie Dazdarian
- SmithcoSoft
- Syn9
- Deleter
- The Awakened
- Seb McClouth
- Rattrapmax6
- Nick Verlinden
- Torahteen
- mennonite
- marzec
- Josiah Tobin
- Regular Columns
- Articles & Editorials
- Tutorials
From The Editor's Desk
Written by Pete
YO DUDES WHATS THE HAPS?
I know, I know, this issue is three weeks late... it was originally supposed to come out before Christmas. (For a laugh, check out Rattrapmax6's Horse Humor comic this month...how untimely, heheh.)
Anyway, what happened? Two things:
(1) Major computer problems on my end. (Everything just happened to fail at once... first it was a hard drive...then while trying to recover the data, my wireless network card went... Then I started getting rampant BSODs and discovered that my motherboard was bad, so I had to get a new one. Then I tried to recover the lost data on my crashed hard drive....so I copied as much as I could to a NEW external hard drive that I bought, and that failed a few days later! And then, to make matters worse, my 19" LCD monitor that I paid $540 for two years ago failed, and I had to buy a new display. ARRRRRRRGH.) But I'm not complaining.
(2) I MOVED ACROSS THE COUNTRY! I am now living in sunny Los Angeles, California. It's quite a change from snowy upstate New York...Let's just say that last night I was swimming and then sitting in a hot tub at 11:00PM. It's so warm here -- 75 degrees Fahrenheit during the day, sunny, and not a cloud in the sky! And I didn't know that palm trees could grow that tall...
Anyway, I'll be out here until May, interning somewhere in the entertainment industry (I'm working on finding a cool internship right now, preferably making documentaries or reality TV). This should be a fun and relatively relaxed semester, compared to the hell I went through in the past six months, so I'll have plenty of time to devote to QB Express these next few months.
Enough about me, though. Go ahead -- get to the magazine!
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, check out the "Official QB Express Article Requests" thread! There have been quite a few articles requested -- and even if none of them strikes your fancy, we can help you come up with something that you would like to write about. 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 MystikShadows
Hi Pete,
Exactly like you said, a short time since the last issue and look at what
we've been able to come up with. A pretty spectacular issue considering
that shorter time between issues. :-). Great work to everybody.
Mennonite, I think he defined his point of view much better this time. I'm
all for FreeBasic, everybody knows that :-). However, when I see someone
flamed for wanting to use the QB and family of compilers, I do wonder what
they hope to acheive by doing this. As far as I'm concerned, If the ask a
general question about which language they should, sure i'll tend to suggest
FreeBasic Otherwise, only if the ask how to do something that can't be done
in QB and Family (pds or vb-dos) will I suggest to them to go to FreeBasic.
I'm thinking if they googled for it (like they should, then they'll see the
existence of FreeBasic and be able to decide for themselves or might have
already decided to not go with FreeBasic for which ever reason (using a DOS
emulator on an handheld, build something for a very old system and so on).
On the plus side, FreeBasic how has a CHM file available which is a good
starting point since most other compilers available do have their help
available without having to go online somewhere. At the very least, before
throwing them into FreeBasic we should ask them what they want to do and on
what kind of hardware they want to do it in just to see if FreeBasic can
answer that call better than any QB compiler could on the given hardware/OS
configuration.
From his emails in this issue (and your replies). It seems to me a bit
weird that there's was a dispute to begin. Basically I have to say I think
memnonite (and you) are right about one thing. Any can decide to start a
project, and anyone can decide which language he/she should be using for it.
I'll use a BASIC dialect whenever I can, but sometimes, depending on the
minding the project needs to be set it to really achieve it's goal (game or
application alike) a different language is simply better suited either for
the role of the project or for the reason why I'd be writing that project.
For example, many compilers are written in C or Pascal, why? because if they
want to use Lex/Yacc or Flex/Bison they spit out C code and mixing that with
another language is almost pointless. If you don't want to use these
compiler technologies, you could, technically write a compiler in any
language you want. I did know that C extremist would be defending C, etc
etc for the other languages. But between QB and FB it shouldn't be a
question of which one is best, it should be a question of which one we want
to use (regardless of whether or not it will run on modern hardware) we can
make people aware that doing a game in QB might not work on XP and that
there is an alternative, FB that will work on modern hardware/OS if they are
willing to learn the new syntax, but moving to FB, today, is more than
simply using a different compiler, there is a learning curve (obviously)
learning the new FB syntax, learning FB IDE or whatever other editor they
might choose to code in, if they want to push their game further they will
have to learn The new graphics librariies (Allegro, OpenGL, etc). Really
depends on the project they are doing. That was my two cents...basically
what the two of you were exchanging in your emails, you're both right, it's,
like memnonite said, your respective points of view on the impact FB is
having on the QMunity. But you said it more than once before, the QMunity
is not about the language, not about QB, PDS, VB-DOS or FreeBasic, it's
about the people :-).
And now back on the subject matter :-) QB Express #16 itself. Let's start
this off with the awards. Adigun's new updates on his website. You know,
some people aren't bad at all graphics wise, some people really seem to know
how to write what they want to communicate with the impact it needs to get
transmitted. Adigun seems to have both of these qualities. It's like going
to his website and reading about his projects and additions is almost a
boost of energy in itself just with the dedication and passion he has for
what he does and you can read that clearly when you visit his website. And
well it's no secret that Adigun is on the top of my list as far as graphics
go. As far as Programmer of the month goes, I've always seen post by
Lithium about different things he's been working. But I think he really made
his mark in the anals of QB history with his Raycasting Engine. Like you
said he's been more active lately but the Raycasting engine really put him
on the next level of programming. Excellent job on the raycasting engine.
A more than well deserved award too Lithium.
Lachie's article on "Writing A Story For A Computer Game". One of the most
insighful articles I've read on the subject. He's definitaly right about
one thing if nothing else, a pac man clone really doesn't need a story.
Many arcade like games don't need a story. Some could do with enough text
to put the user into perspective for what he or she is about to see (some
year in the future for example to tell the player that he's about to see
things that don't exist today, nothing more really). But if you're going to
write a game that does need a story, then you do need to spend time to write
a good story. Best example of that, Quest for Opa Opa which needs no
introduction today. Of course, Lachie's "Searching for the Unknown" is
keeping up strongly with this month's submission. I always wonder what game
he'll find next to put in this series and well he really picks them good and
seems to have a knack for talking about them, describing them and letting us
know all about them. Great work Lachie, and I can't wait to see what I'll be
reading in your column next.
Rick Clark's article on Managing Complexity and on FreeBasic's UNION
structure were very insightful. I think that anyone who has worked on any
bigger project, or would like to, should read his article on managing
complexity. This article becomes even more vital the bigger the project is
because that is, after all, what programming is all about, managing
complexity and if Managing Complexity is applied early in the development
cycle and maintained throughout it can all help with not feeling overwhelmed
by a given programming task. I also really liked the way he uses UNIONs in
his DDD game too. Not many people, like he mentionned used unions but as
they can see from his example it can prove to be one of the best means of
organizing and managing your data. Now if FreeBasic had PCOPY in text mode
(SCREEN 0) like QB, PDS and VB-DOS have, it would be grand considering FB is
supposed to be an evolution from these languages to the next level :-)
(sorry guys, I'm an ASCII developer, so I have to try to push this feature
whenever I get the chance ;-) long live ASCII hehe.).
Agamemnus' "Programming Language Syntax Tenets" Showed me things about
programing I've definitaly experienced first hand (now that I think of it)
but never actually sat down and pondered upon, until now. Very informative
article that really helps understand why different programming languages are
the way they way the are. There is definately a ratio between flexibility
and universiality. Like wise there is also a ratio between flexibility and
simplicity that help categorize a programming language. For example, I've
always wondered why languages such as Pascal, C and Ada did not support
string variable and/or string literals in their version of the SELECT CASE
statement. The main reason is for speed of execution of course, but when
you think of how simple and easy to understand a select case using String
literals can look when others are viewing your code, I say all languages
should implement it (even if they would have to add a note that String based
select cases might not be as fast as Numeric ones. So one thing I would
like to see is a more detailed coverage of the subject matter. This version
was good enough to grab my attention about the subject, now I'd definitaly
like to know more, much more about it. But great work on opening my eyes
Agamemnus :-).
Immortis' "How To Program A Simple Text Parser In FB/QB" I think presented
an excellent way to parse a string. His article finished with "If I hear
any requests, I might show some practical uses of this code or even
something different (if I can think of anything...)" Well Imortis, consider
this the first of those requests. I would definitaly like to see how to use
this for practical use. Let's see what the second of this series will teach
us next.
As a last Item on the list, I would like to address Na_th_an personally
here, well not so personal in a letter to the editor, but oh well :-).
Basically, I'm still very much wanting to read part 8 of his IF tutorial.
I'm probably the biggest fan of that series and since part 8 should be
closing the gap of the 7 previous parts of the series and making it all fit
together, I can't wait to see and read all about it. So, if Na_th_an has a
chance (and read this paragraph ;-) to make it happen, then I hope he can
find the time to make that part 8 a reality :-).
A very awesome issue, that's the least I can say about QB Express's sweet
#16 ;-). One of the best things about it, is to see how much mmore advanced
projects the same QB people are tackling thanks to FreeBasic. Would you
look at these projects happening lately? I'm amazed and most definitaly
glad to see it all happen. And I'm sure there's plenty more projects in the
making that are just waiting to be "developed enough to be worth showing to
the world" too. Everything is moving forward and well I'm just glad to see
that big wheel turning. Excellent work to everyone involved in QB Express,
it's really fun to see where the QMunity, the projects and the the rest of
the QMunity see where they are going and I can't wait to see what will pop
up next. Until Next time.
MystikShadows
Stephane Richard
Great feedback, as always! Every month, I look forward to reading your letter (as I'm sure all of our other readers are too)!
As for the whole mennonite situation, I think you hit the nail on the head....and now I'm gonna let the whole thing drop. Interestingly, even though mennonite decided to quit writing for QB Express, he began a new mini-magazine about The QBasic Forum ('apostrophe) and gave me and QB Express exclusive rights to republish it. Even when he vows to never write for QB Express again, he still manages to contribute to the magazine. So I thank him for that.
I look forward to hearing from you next month!
-Pete
Letter From Lachie Dazdarian
I'm starting this letter on the 9th of November though I know I won't be able to send it for several weeks from today. I want to write this today while my impressions on issue #15 are still fresh. Also, there are few things I really want to say which are making me difficult to concentrate on other things, like preparing an exam. This current situation where I'm able to get online only so seldom is really irritating. It doesn't allow me to present my opinions about the community and the magazine when they are still current and in general, to be a very constructive member of the community(in the sense of being in the loop; I'm not talking about making contributions). I can assume that this also irritates people who email me questions since they have to wait for weeks to get a reply. When I finally get online it's a crazy situation where I need to check all the posts I know I should check and email all the people I need to email in couple of hours. Proper roaming through the community forums is just not an option. For example, I didn't have time to read issue #15 online so I missed the news about the new version of FBIDE and didn't download it. Now I have to wait for like a month to be able to download it. *sigh*
Other aspect of this situation relates to my college where I'm unable to work on my projects on an efficient way since that requires often consultations and similar. All this leaves unnecessary long gaps between exams and forces me to postpone my college projects which will probably make my end of study very frustrating. I also feel I should be doing some sort of part time job now but since I don't live in the capital that is not going to happen. Bus fare prices are very high now. Stupid oil crisis.
For some reason issue #15 left me with so many opinions and comments needed to be written down.
I really want to start with critics about the very editing. I've noticed that my letter in the issue #15 is not the version I have in my archive.
Check this paragraph(original version):
"I've read in the issue #12 your thanks to MystikShadows for pre-formatting his articles. First of all, I didn't know you could do it so easily and format it outside the entire magazine. Shows my lack of HTML knowledge(or is it some other lingo?)."
While this appears in the magazine:
"I read in issue #12 your thanks to MystikShadows for his pre-formatting of his articles. First of all, I didn't know you could do that. I didn't know you could do that one article at a time. Shows my lack of HTML knowledge."
Duh? Did I send you something so awfully incoherent like that? I was sure I sent you the latest version. I don't know. I just want to be sure what I sent you and that this "change" is not a result of proofreading. But this is probably my mistake.
Also, why the second half of my letter has (?) where (') should be? What's up with that? It made my letter look very sloppy.
Few news were entirely in bold like "Adigun Azikiwe Polack AFLIB2 Progress Report" while that shouldn't be(I assume).
I have to comment the way you played with the screenshots in my articles. I know you are the editor and have the right to choose how the articles will look in the magazine but I really think some of your action were unconstructive. Some of the image shiftings are probably the result of you working in 1024*768 or some higher resolution and I work in 800*600 resolution(the best if you ask me, others are just murder of a good eyesight). Still, I don't understand you shifting screenshots I've placed outside a paragraph into a paragraph. Why do you hate screenshots placed outside paragraphs so much? For example, screenshot of the MADMIX's main menu is on the end of introduction section for a reason because the entire introduction is about QBasic pacman games while the very end mentions MADMIX. Putting that screenshot in the middle of introduction where I jab about QBasic pacman games might be confusing for the readers. When I think about the next two articles I already sent you I fear what you might to with the screenshot in them since the placement of screenshots in those two articles is especially important.
Err...the next thing happened in few previous issues too. Some HUGE images mess up the placement of an article in the sense of prolonging its edge to the right. I don't know if that is a problem of IE. This happens in issue #15 in "Graphical User Interfaces - A Complete Study Part 1 - GUI Design" article. Each time you notice that some large image messes up an article you should try to reduce its size and make a link of it in case the reader wants to see that image in full size. That's what I did in Bozula Block Buster review. A similar mistake I noticed with larger images placed in a text box making the text beside the image unreadable(part of it being covered by the image). You should consider "taming" HUGE images in the next issues.
That would be about the editing.
I wish to say few things about the current events(well, they were when I wrote this letter) in the community. I'm really sorry so many people(including you) approached with distrusts and some sort of jealousy(not you Pete) to the new management of QBasic.com. First about those "The QBasic Forum" bozos. I'm calling them bozos because they are asking for it. Above all, they should calm down. Mark Wilhelm PAID for the domain and he has all the right to remove the link to the old forum at Network 54 if he likes. If I was on his place I would do it. Why? Because I would want for MY site to feature MY own forum under MY control because I PAID for the domain. The old moderators from the Network 54 forum should ask Mark if he could make them the moderators in the new forum which is something they deserve(at this point) and which is something I think Mark would agree too. Any situation is better than what it was till now with QBasic.com. The only damage Mark can do is sabotage the community on purpose. Doing something like placing a picture of Tubgirl on the main page with a message under it "HOT ENOUGH!". Somehow I doubt this will happen. :P I just think he doesn't deserve such irrational suspicion. We should offer suggestions and help and stop being so paranoid. As for the debate about QBasic.com featuring FreeBASIC content I have to agree with V1ctor on this. I think it's enough to offer information about FreeBASIC and links to appropriate sites. Let's get real, QBasic is a different compiler and FreeBASIC is not the OFFICIAL update of QBasic. If any site has to remain true to QBasic then that site is QBasic.com. If you don't like that then don't visit the site. Anyone using FreeBASIC has absolutely no right to demand the userbase of some other compiler whatever his or her opinions about that compiler and its link with FreeBASIC are. So I'm personally against FreeBASIC content on QBasic.com except for information about FreeBASIC and links to FreeBASIC sites. That's more than enough. Anyway, QBasic.com was for years outside the real QBasic community(based around VPlanet, qb45.com and qbasicnews.com) so claiming that QBasic.com belongs to the community members who switched to FreeBASIC is wrong.
As for mennonite, I mostly disagree with him and find his dislike of FreeBASIC childish. I can assume that this attitude comes from his hate toward Windows which I find difficult to understand since his bellowed DOS is also a Microsoft product. I generally think that Windows are criticized way too often with very little real arguments. My PC(with Windows XP installed) serves me so well from coding in FreeBASIC, doing college projects to playing QBasic games. Some people forget that the majority of computer users are not interested in computers. They simply want to have an OS that serves their needs on the most efficient way. Anyway, the way mennonite behaved(through his posts to you Pete) makes all of us doubt his maturity. I hate using that word since it makes me sound condescending. But really, I can't escape the impression that he is a very inpatient person who reacts with rage on any obstacle and changes opinions on hourly basis. Definitely a troubled boy who should grow up. The only thing I didn't like in your response Pete is your opinion about rude behavior toward "annoying" newbies. I highly disagree with you in that. There is a very thin line between justified and unjustified rudeness and people go across that line more often than not. I've experienced similar rudeness without asking stupid questions or being annoying and that rudeness was almost always a result of that person's inability to help me. If you can't or don't want to help someone why in the world attack or trash that person? Really? I don't see any sense in that. Be kind and warn that person about his or her poorly constructed question. The only real reason to attack someone on the Internet with rude words and names is if that person constantly spams the forum or really has a poor character, where he or she keeps insulting everyone or is openly a racist, pedophile or whatever. I don't know. But stupid questions are not a reason for bashing. Period. Anyway, not all people have time to search for the right tutorial, including me. Their time on the Internet might be limited(you don't know) and pointing them out to the right tutorial is a blessing. Also, many tutorials do more damage than help. And believe me on this because I remember by beginnings very well. I also have some experience with newbies and know what kind of mistakes they do. Mistakes mostly caused by over-simplified and poorly constructed tutorials. That's one of the reasons why I'm planning to create a series of articles about game design oriented programming which will allow newbies to learn game design in few lessons and skip several annoying and unnecessary long stages in learning how to program games. I just know how indifference of moderators in forums toward bashing can be destructive and where it leads. Mark my words.
Phew, I'm not even near the end of this letter. I'm scared too. :P
I'm quite surprised with the poll results(What is your favorite finished FB game?) and very reserved to them. Looking at the number of votes "Other" got makes me wonder did the people who click on it understood the question. The question was about your favorite FINISHED FB game. I would really like to know on what game(s) these people were thinking and do they honestly think that this "secret" game is better than Red Jumpy Ball or The Quest For Opa Opa or ArKade or Battle Pong or Poxie or the brilliant The Griffon Legend. If you ask me, jealous losers voted for "Other". I apologize if I'm mistaken but I doubt. Like I said, show me this game and I'll apologize. I forgot to vote in this poll like in so many before. And the last time I was online I again forgot to vote. Crap.
In the news section you mentioned my articles site. If anyone is wondering I'm having problems logging on to my account(some stupid new college firewall) so I was unable to update the site on the 7th of November and I don't know if I'll be able to do it any time soon. But two updates are ready. To those few who actually visited the site I can only promise it will update. Somehow. :( It's not a site went dead, I assure you.
Also, MystikShadows described the preview of the MySQL QBasic games database I'm creating as a site. I don't want for people to get the wrong idea about this preview page. It is not a site nor it resembles to my idea of the QBasic Game Directory site. It only features some of the RAW content that will appear on the site. The only reason why I'm showing this preview is because I'm having problems running some of the QBasic games so in order to get help on that I need to show people that I'm actually doing something. I need to show them that this project just might be successful and their help won't be in vain. But for some reason nobody is offering help in testing these game. I barely got help regarding one of my games(Dark Quest) from Zap since I can't score and critically describe my games. I think the site will have to open with around 50 games on the pending list because the community simply dropped the ball on this. I think I'll have to find one person who has an access to several PCs with several Windows version to do the testing of those game since my requests are not bringing result. But at least any critique, when the real site opens, regarding so many games on the pending list won't be my fault.
It's nice to see Adigun's work on AFLIB2 going so well and I hope it will be GFXLib friendly or will have all that GFXLib has plus more. I'm having problems getting certain routines necessary to port LONG to FB(I will obviously have to cut out some of the game's features) from Eric including 8-bit translucency and sprite scaling and rotation. BTW, what's up with Eric? I didn't hear from him over a month. I'm stuck without him. Anyway, hopefully AFLIB2 will solve most of my "game design oriented programming needs". He-he.
I'm surprised to see someone still developing in FutureLib(I'm referring to Cadisman from the Gallery section). I hope that Brad Lanham is aware for how small userbase he is developing. Someone should suggest him to switch to FB.
I can't say I'm happy with the quantity of articles and tutorials in this issue though the decline, compared with the issue #14, is almost ignorable. But if you take out my and MystikShadows contribution you will have 5 articles and 3 tutorials. I'm not presuming the quality of my articles here, I'm just saying that without certain 3-4 contributors this magazine would look much smaller. I really hate when some tutorial series stop to be released like Rattrapmax6's "A Course In FreeBasic" or Na_th_an's "Coding A Parallax Scrolling Platformer" which is almost forgotten(issue #10, remember?). I would really like to see more people sticking with their series once they start them. All in all I feel a certain slowdown in the community which is, I admit, just my impression. What I can notice from the magazine and from the number of replies I get on some of my topics(an the quality of replies) in www.freebasic.net forum the community is not active as it was few months ago. I think too many people are concentrated on their projects or just concentrated on something other than the community at this point. Just look at the tutorials section in this issue. If we ignore Jonathan Wallace's tutorial about group A.I. others don't feature a single line of FreeBASIC code. Like I already said, I'm planning to do something about that by starting a concrete, "all around" game design oriented tutorial. Anyway, I'm sure the situation will get better. That is if you agree with me that it's not the best.
Both comics were very amusing in this issue and I applaud both Rattrapmax6 and Matt2Jones on their work though I still dislike the approach Rattrapmax6 has to drawing.
urger's article about writing was very useful and just what I needed. Remember all those questing I email you about grammar? Matt2Jones "Game Production" article was strangely insightful but I don't agree with him entirely especially with his statement that making a game faster makes it better. I think it would be better to say that unnecessary slow pace and delays in a game are a shameful rip-off of user's free time.
I think I should end this horridly long letter now. Like I always say, take my comments in good will as they were written in good will. If I'm wrong help me realize that. I so hope some of this dribble will relevant in a month.
Best Wishes, Lachie D.
P.S.(Oh, noooooo!)
This was written on December 8th before I got online.
I had many plans for this month but all of that had to be postponed because I decided to participate in the Roguelike competition. I know, I know. I promised I won't start developing another game before finishing LONG. I got hooked on the idea of creating a Roguelike game with a turn-based battle system after reading the last issue of QB Express. For a long time I wanted to create a game with a turn-based battle system and this compo seemed like a nice opportunity. I just couldn't help it. Once the thought enter my mind I had to start to develop my entry or I wouldn?t be able to sleep(help me). I hope those 2-3 persons who are waiting for LONG will forgive me for being so weak. Since I was developing a brand new game for the last 30 days I did nothing for QB Express and very little on the QBasic Games Directory project though the work I planned to do was minimal. I'm hoping to get some useful PHP tips next time I get online and will attempt to create at least the skeleton of the site during the holydays. Where's my new game, you must be asking yourself(just work with me :P). Well, it's bloody not finished! Argh! I spent over 90 hours (I timed it this time), around 25 evenings and it still isn?t done. Ugh. I gave up a week before the 16th(the day I'm emailing this letter) since I realized I wouldn't be able to complete my entry(named Mini Space Rogue) properly and since I needed some time to decompress for the college obligations. I didn't want to finish it.....hmmm...I would say on Croatian "na vrat na nos" but I don't know how to translate that to English. All in all, I need more time. I want to be happy with the final version. Expect the release somewhere in the middle of the January 2006(stop rolling with your eyes) and don't expect anything grand. First of all, it's a Roguelike game. No dialogues or some complex plot. Just endless walking through dungeons. Well, in Mini Space Rogue it's through an abandoned space ship. Anyway, Roguelike theme was very convinient for creating something not very demanding in the graphics department(static graphics) and even less demanding in the story/plot department. And that's the main reason why I'm pissed for not being able to fininsh Mini Space Rogue before today. It won't be anything special. I've sent you Pete the crippled version. If you want to say few words on it be my guest. Just don't SHARE the archive or I'll think bad of you(how threatening).
Thanks for the great letter! I'll respond to a few parts (sorry if I skip something important -- it's a very long letter).
I'm sorry about your issues with the formatting and proofreading. It's pure negligence on my part. I make QB Express on a computer with a 19" monitor at 1280x1024 resolution, and it looks great at that resolution, and also at 1024x768. I know a lot of stuff in the layout gets screwed up at 800x600 resolution, and I apologize. If I had more time, I would gladly reformat the magazine for different screen resolutions, but I'm just too busy. I release the mag every month knowing that it will look wonky on anything less than 1024x768.
I guess I've just got to cut my losses. Since only 17% of my site's visitors use a resolution of 800x600 or lower, (and that number is dropping every single day), I figure that I should tailor to the majority of my visitors. The up side is that people like to look at big images, so using HUGE images means that at high resolutions, the magazine will look much better. I could easily fix the formatting and proofreading problems if I had another full day to spend on each issue...but I just don't have the time, unfortunately. If anyone wants to volunteer to help me with this, it would be great.
As for the discrepancies between the final version of your letter and the one that was published, I'm not sure how they came about. As you know, I do very little proofreading on my own since I don't have time. That particular letter might have been edited by urger when he did the proofreading (though I doubt he would have edited it like that to make it less intelligible). As for the ? marks instead of apostrophes ('), that happens when converting between raw ASCII text and ANSI text. Sorry I didn't catch it when I published the issue.
--
I also have noticed the slowdown in the Qmunity in the past few months, both in number of posts and submissions to QB Express. It seems that every issue since #12 or #13 has been a lot smaller than they were just a few months before. The total number of posts on some forums has dropped significantly -- The Basic Network barely gets any posts these days, QBNZ is almost dead, QB45 is down to just a few posts per week, and QBasic News and my site's forums have also slowed down. In fact, the only forum that's gotten more active recently is FreeBasic.net's. The number of new program releases has also slowed down.
Why? I think what it comes down to is that "FreeBasic Fever" has died down. FreeBasic is no longer a new thing, so people aren't as excited about it as they were at this time last year. There simply aren't as many finished releases being made right now. So in that respect, the Qmunity has slowed down. However, the Qmunity is still WAY more active than it was when I first started QB Express back in the summer of 2004 -- in the days BEFORE FreeBasic. Just look at the "Project News" briefs this month. There are so many HUGE projects in the works, including a lot of awesome games and libraries that will undoubtedly set new standards for the FB community. Sure, the number of releases my have decreased, but the quality of the releases these days is much higher than the before. (What would you rather see, Lynn's Legacy or two dozen graphics demos?)
-Pete
Have a letter for the editor? Send all your rants, raves, ideas, comments and questions to pberg1@gmail.com.
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!
Should Pete remember to post polls from now on?
Genre | Votes | Percent | Graph |
Yes | 1 | 100% | |
No | 0 | 0% | |
1 Total Vote |
Whoops! It's been a very busy month, and I completely forgot to post a new poll. (The one vote in the poll above is from me, heheh...) Anyway, there WILL be one in the next issue, promise.
News Briefs
News from all around the QB community, about the latest games, site updates, program releases and more!
QB Site News
- QB Top 50 Relaunches
-
After a hiatus of several years, AhmedF has relaunched QBTop50.com! This QB / FB top sites list couldn't have come at a better time, now that the last remaining QB top sites list (the QB RPG Top 50) went down a few months ago.
Unlike past top sites pages, the QBTop50 rates based on Unique Hits to registered web pages, so it is much more difficult for webmasters to cheat than in the past.
The Pete's QB Site / QB Express voting image for the QB Top 50. Shameless self promotion, I know. So sue me.
|
If you've got a QB or FB website, I encourage you to register it with the QBTop50. It will help give you free publicity, and will almost certainly drive more traffic to your site.
News Brief by Pete
- A Ton of QB GUI News
-
Todd Seuss and company have been keeping up to date on the QuickBasic GUI Blog launched back in November. In the past month and a half, there have been a few dozen news posts on various happenings around the QB GUI Community. In fact, there are far too many releases and news updates to mention here, so you should go and check out the blog for yourself!
News Brief by Pete
- FBIde Official Site Launches
-
The new site design for VonGodric's popular FreeBasic IDE FBIde, has just launched. You can view it at either http://fbide.freebasic.net or http://fbide.sourceforge.net. The site now sports a brand new CMS created by VonGodric specifically for the site, and a snazzy new design. Sweet!
News Brief by Pete
- The Code Post Makes A Comeback
-
Dav has resurrected The Code Post, a QB message board from a few years back where users were encouraged to post snippets of their code. Here's some info from Dav:
The once (kind of popular) Qbasic code post I ran a few years back is returning - this time adding FreeBasic to the list.
The code post is a forum driven site where programmers share their work with others. The main site is still being developed, but a temporary forum is up and running.
More languages will be added. Code packs will be assembled containing all contributing code posted and be available for download, if it gets that popular again...
For those new-comers that what to see what the code post was all about, you can download the last Qbasic source-code book right here...
http://www.thecodepost.com/codebook.exe
It contains all the source code submitted before the site was closed - over 100 snippets in it.
The Code Post is hosted by Plasma (Phat Code), and base don Fling-master's Flingforum mesage board script. Go check it out...and post your code!
News Brief by Pete
Project News
- Dark Knight Software Releases Dark Ages II: Engel
-
On December 11th, Dark Knight Software finally released the sequel to the well known Dark Ages I. It's called "Dark Ages II Engel". Here is the description of the game that you can read about and download from the website:
About Dark Ages II: Engel
Dark Ages II: Engel is a free computer role-playing game that follows the story of those three initiates of the Thieves' Guild. The plot is non-linear in the sense that key points in the plot will require a choice. That choice will lead to different quests without turning back. The world will change according to those choices. I hope to add replayability (is that a word?) by allowing the player to start the game over after they've won and play a whole series of new quests and still win the game. How it differs from most non-linear games is that it does not change how the game ends; merely all the content in the middle. A lot of games change the storyline to fit non-linear choices, but the quests and tasks are the same. In the case of DA2, some quests will never become available. You will just have to play again to try them out.
Here are a few screenshots to give you an idea of the type of game as well as all the hard work that has been put into this game's production.
The game is currently in its release candidate 4 (RC4) state which brings it very close to its official release. In fact, they state that the official release should be out by christmas. All of you readers are encouraged to download the game and give it a try see if you can spot a a final bug that can be corrected before the official release date.
News Brief by MystikShadows
- Yagl - Yet Another Game Programming Library
-
Yagl is a high-performance 2D game programming library based on OpenGL and OpenAL, outperforming SDL and Allegro. Its purpose is to be a fast, easy-to-use general-purpose game development tool. It is completely object-oriented and supports fast graphic blitters, easy integration with OpenGL, 3D sound, keyboard and gamepad input, and networking capabilities, native support for loading oggs, wavs, aus, snds, bmps and pngs. Also, wrappers for C and FreeBASIC exist making it attractive for procedural languages too. you can get more information on yagl at http://goddess.selfip.com/yagl
News Brief by marzec
- duke4e Creates an Arkanoid Clone
-
duke4e has been busy these past months with the creation of his Arkanoid Clone. As most of your know Arkanoids hardly needs an introduction. It is an evolutionary step to the classic breakout type game and features many addtions to the game to help make it more interesting to play. The game seems to respond well to user input and performs quite well even on lower end systems which broadens it's range of users.
Here are a few screenshots of the game in action. You'll see quickly here what this game is all about and what you can expect out of it.
You'll be happy to know that on December 9th duke4e has release the official version 1.0 of this game for all to download and play.
You can follow this game's development and user's comments right here on the Freebasic.net Project thread forum.
News Brief by MystikShadows
- Mambazo Anounces Arena: To The Death
Just last week, mambazo announced an ambitious new FB fighting game entitled Arena: To The Death. It's still in its early stages, but mambazo has big plans for it. Here's the full report, copied from his Freebasic.net post:
Brief:
A small project i've been tootling about with for the last few days. It's still in the very early stages of development.
This is inspired by the fighting system of the age old game Budokan. So button bashers beware! Its all about timing and precision ([i]note: you can beat the single player opponent in two well placed moves![/i]). There are 6 attacks, 4 tactical moves and 3 blocks. More attacks will be added at a later stage.
I hope to make at least 10 different fighters, with axes, maces, etc etc!
Plans in development:
The game is taking a more interesting turn! You will mainly play the part of an Owner. You'll be able to buy & sell fighters, enter different contests, win cash, and manage your fighters!
Wealth
You receive coinage for each battle you win. Use your Wealth to purchase more fighters and maintain them. You can also spend your earnings in the Black Market to increase your chances of winning. If one of your fighters is no longer of use to you, you may sell him.
Reputation
Before each fight, there is a chance a stranger will approach you with a request. You can choose to accept or reject the offer.
The higher your reputation the more likely you will be asked, and the more money you will be offered. As your reputation increases, the tasks will get harder. If you complete the task, you gain a reputation point. If you fail, you loose a point.
Depending on your reputation, you may or may not be eligible to enter certain arenas.
The Alley
This is where you will most likely start your career. In the grotty sidestreets, out of site. The winnings are low here, but the entry fee is most forgiving. You will not face any heros here, just clumsey unfit oafs, desperate for money.
The Battlegrounds
Whilst costly to enter, considerable winnings await you at the battlegrounds, provided you can hold your own. Pit your fighters against the commonfolks' lesser heros in public. Let your name spread through the city!
The Grand Arena
Only the most barbaric warriors remain standing after battle in The Grand Arena. Bleed your way to true fame and wealth while thousands of onlookers gasp and cheer! The entry fee is hefty and the winnings are glorious.
Fighter Stats
Health - The amount of damage he can take.
Stamina - Affects the amount of damage he can deal. During battle, he will tire with each swing of his blade.
Vitality - The rate at which his stamina regenerates.
Strength - Affects the amount of minimum damage he can deal.
Range - How far he can reach with his blade.
Experience - Gained after each battle. The more fights he wins, the more valuable he becomes.
Worth - For use in trading.
Wages - The amount this fighter costs you each week.
Black Market
The black market is where you can gain an devious edge over your opponent before entering the arena.
Doctor - Heal your wounded fighters.
Stab - Wound your opponent before the battle. Make him weak on his feet.
Blunt - Blunt your opponent's weapon such that he cannot wound you deeply.
Poison Blade - Poison your own blade. Make your opponent suffer.
Studded Boots - Suprise your opponent with a steel kick to the ribs.
The Devil's Drink - Drink this before battle for a more, stimulating, fight.
Undercoat - Feel indestructable with an extra layer of armour.
Gamble - Be sure of yourself and place a bet to win, at the Grand Arena.
Notes:
The fighter manager part of the game has not been coded yet, as I wanted to make sure I could make a, somewhat fun, fighting engine first.
In the Single Player zip there is a file called [b]moves.txt[/b] showing you your keys (W A S D, G H), and all the moves currently available.
Comments & critisisms welcome,
Enjoy.
Download:
Download Arena.zip
note: on the first seletion screen, press 2 to watch the PC fight itself.
Download Arena_Update_07_01_06.zip
Note: You need Arena.zip also to use this update. Just unzip into the Arena folder and let it overwrite the files.
News Brief by Pete / mambazo
- Zero G Academy Splits Into 2 Games!
-
Syn9, being the prolific FB developer that he is, has decided to turn his upcoming racer into two different games:
I split Zero G Academy into 2 games. A gunship game that is currently untitled with gameplay like the Jungle Strike / Soviet Strike games. And Zero GTR, which is the sequel to Zero G.
-syn9
Here's the logo from Zero GTR:
There are also several more screenshots from Syn9's upcoming projects available at his website, Syn9's Hideout. They include the Gunship game, as well as an upcoming 3D RPG made in QB and a Turn Based Strategy game. Incredible stuff, if I do say so myself!
News Brief by Pete
- Turn-Based Strategy Game Making Progress
-
The engine for the game has progressed quite nicely thanks to syn9 and Eclipzer. The engine now sports randomly generated trees, lakes, rivers, and bridges. Line of sight has been implemented, as well as movement squares. Rattrapmax and xteraco have been busy making new models, such as a new mech (Rattrap), new buildings (xteraco), and more.
By next month, we expect to see animated and textured models. We also plan to have the main game loop done. Ryan is working hard on his network code, a big deal in turn-based strategy games. That's right, the game will have full multiplayer support. SSC has been working hard on the game rules, and the design document. Thank heaven for him, because we'd be lost without those rules. I, Torahteen, have little to do at this point in time, other then to look over the project to see that it gets done. Truthfully, I enjoy my job ;). Here are two more screen shots to show you all just how much work the team has been putting into this project.
More info next month. Until then...
News Brief by Torahteen
- AFLIB2 Status Report
(As of December 19th, 2005)
As some of you may already know from his many update posts on the different forums, Adigun Azikiwe Polack has been relentlessly busy working on his AFLIB2 project. The forum threads are of course FreeBasic.net thread and the QBasicNews.com thread. I've been covering it's development for a few months already and it seems, every month, the new functionality just keeps on growing at a good and steady pace. Here is the rundown of the new functionality added in the course of the last month.
- AFLIB2 Filters: Yup, AFLIB2 now has image filtering. the ability to filter colors out of a picture which is used to add some pretty impressive visual effects.
- AFLIB2 PP256 Based Scoring: Specialized routine for managing and displaying scores first it displayed the scores, now it displayes the scores with translucency which according the screenshots on the forums, really gives a great effect.
- AFLIB2 Horizontal Screen Flipping: I think this one pretty much speaks for itself. The ability to horizontally flip (often call a horizontal mirror) of any given pictures.
- AFLIB2 Can now be compiled as a whole: Indeed Adigun has prepared all of the code so that it can be compiled as a whole library. As mentionned by adigun himself, the compiled library stands at around 7 megs which is a big size indeed. However, for the functionality it offers (and the work it saves the programmer) I don't believe that 7 megs (3.5 Megs minimum) isn't all that alarming.
- First AFLIB Sample Program Available: On December 12th, Adigun offered us a first sample program available to be viewed. You can see from this example that it really seems like AFLIB2 is well underway to making the code you'll have to write as short as possible using this project. Here is that sample application.
It's important for you to know that these additions are available in all screen resolutions supported by the AFLIB2 project. Also, Adigun has started the tedious task of documenting AFLIB2. With all the functions, it might take him a while, then again, it might not. So be on the look out for upcoming (as soon as he possibly can) of a no doubt very detailed documentation for this very elaborate library project.
News Brief by MystikShadows
- Black Satin!
-
Nekrophidius has announced a new FreeBasic fighting game he has in the works, entitled Black Satin. The game will use marzec's speedy YAGL library, and is sure to have a lot more twists than that. Here's the word, straight from Nekrophidius/Nodtvedit/sn0ball (apparently)...
Black Satin is a fighting game not unlike other 2D fighting games, with one exception: all the characters are female and they're all 3D rendered rather than hand-drawn. Anyways, here's an early shot of the game working...this is just the vs screen and it doesn't show the graphical effects I used here but anyways...
This shows Midarana (left) and Desiree (right) about to catfight. :)
The one thing I've noticed while testing yagl is its amazingly high speed...even on my crappy old TNT2 video card. Anyways, I'll get some screenies of the game "in action" soon, and perhaps put out a prototype build within a few days or so...
For the record: anyone from the MUGEN scene of old should remember this game...I, as "sn0ball", was developing Black Satin for MUGEN back in 2000-2001...my star character for the game was "Megan" and she was the only character to ever be released "into the wild". Once MUGEN "died", I dropped this project...
I'm sure it doesn't need to be said, but Black Satin sounds awesome...I for one can't wait!
News Brief by Pete
- Lynn's Legacy Progress Update
-
Here's all the latest on Lynn's Legacy, courtesy of Josiah Tobin!
MAPS
Maps are going great, thanks to Cha0s' custom-made map editor, 'Gmap', that has existed and gone through many different iterations since the start of the current development process. All the overworld maps are complete, and the dungeons are currently the main focus. Dungeons 1-3 are fully complete (though 2 and 3 are currently sans-boss), and dungeon 4 is about 1/4 done. There are eight dungeons in total, the first six of which play essentially like the dungeons in Zelda: A Link To The Past. The last two have a slightly different focus and purpose. (no spoilers, sorry :p) We were thinking about releasing a version of the game that is complete up to the end of the sixth dungeon, once we get to that point-- Basically a 'teaser' version of the game, with most of it there, giving us time to work on the somewhat ambitious final section. IF we do go through with this plan, the idea would be that we would have an earlier release date for most of the game, and while people play through that, we'd be working on finishing up the 'lost' segment-- Hopefully we'd finish it before most people beat the released version. Anyhow, that's all speculation; we're still not certain, and the idea was very vague when first mentioned anyway, so don't expect anything.
Note: All the dungeons were planned out beforehand on paper; they're all fully designed, barring the last two-- The plans are simply used as reference for the actual maps, and the smaller details of the individual rooms are all thought of and implemented during editing.
GRAPHICS
Graphics are all complete, for the most part, and have been for some time now. There are a few tiny exceptions, like certain little sprites I forgot to do, that are always taken care of whenever the need for them arises. For all intents and purposes, the graphics are 100% done.
MUSIC / SOUND EFFECTS
Music is all 100% done. Sounds are being done along the way, as they're needed. Since they're so simple to do, this isn't really a problem.
SCRIPT / DIALOGUE
The Lynn's Legacy script is fully complete, is roughly 40 pages long, and does not include descriptions of any of the dungeons, except for key story points that occur within them. For the most part it simply details the path of the game, and every line of dialogue within. I'm very proud of the script-- I honestly can't wait for the game to be finished so I can see the reaction to the final section of the story. On the topic of story, it's interesting to note that originally, the game wasn't intended to be too plot-heavy-- it was simply meant to be a somewhat basic action-rpg with only the essentials of a story to hold it together, instead focusing primarily on fun factor and how it played. When it started out in mid-2003 (I think it was 2003? Cha0s may be able to correct me here), the concept and story were COMPLETELY different, the only thing in common with its current iteration being the name, and the type of gameplay. Maybe I'll elaborate more on this in the future if anyone is interested, once the game is finished.
RELEASE DATE
None. :p Not yet, at least. I know you've all heard it before coming from various projects, but it will be finished. Maybe we'll have a better estimate when we're closer to our goal. As mentioned before, the main focus for me is currently the dungeon maps. The amount of time it takes to complete a full dungeon varies-- The second dungeon took several weeks (more due to apathy than anything else) while the third was completed in about a day after working on it almost constantly. I'll also be working full time very soon, but you can be sure that I'll spend every second of free time I have slaving away on the maps. :p
News Brief by Josiah Tobin
Competition News
- Rogue Compo Update
-
(As of December 19th, 2005.)
As is now tradition, and as you've come to expect, I am bringing you now an update on the ongoing Rogue like compo currently happening on the FreeBasic.tk forums.
First off I would like to announce that Lachie Dazarian has now joined this compo as you can read in this FreeBasic.tk forum thread. Indeed, on December 16th, Lachie announce his interest to join this compo with an already impressive entry as you can see from the screenshots he supplied on this thread.
Now for the update. From what I have read in reply to my monthly post, it seems some people have done alot, others have had less time to work at it this month. My thread on the monthly update can be read right here. Here is a rundown of what has happened this month.
Andrew Collins reported the most amount of changes this month. And what an impressive list of change it is. Here is his very own reply with all the details: (fasten your safety belts, there is a lot).
"These are the changes since the last build that I reported to you....
0.17e 12:30 AM 11/19/05
Monsters use spells now and fixed some bugs
0.17f 9:04 PM 11/19/05
Added some more spells and did some work on the parser.
Added some more monsters.
Monsters that can (and will) teleport, when you hit them.
You may now enchant(and disenchant) items.
Added a save game feature(exiting the game autosaves)
Lowered restrictions for special item generation so more will be generated.
0.18a 10:29 AM 11/20/05
Went bug hunting.
Found a bug in the spell parser and fixed it.
Found a bug in Inventory and fixed it. X2
Found a bug in Melee combat and fixed it.
Added the ability to drop multiples of the same item on one tile.
Found a bug in the Item Generator and fixed it.
Arrows must be equiped to use them with the bow.(Quiver)
Arrows stack when equipped in the quiver.
Inventory auto sorts by tval's(might color coded in the future)
Added more Items and Item specials.
Added more spells.
I've given Jocke his own spell! Look for it on a scroll.
Added more monsters.
Player can now die!
0.18b 6:40 PM 11/21/05
Fixed a game killing bug in the spells sub.
0.18c 7:35 PM 11/21/05
Fixed a small inventory bug.
Removed the numbering system from the spells.
Added more spells.
Gave Ryan and Myself a spell.(I'm not very flattering with spellname's)
I did reverse the names to protect the innocent.
0.18d 6:45 PM 11/22/05
Fixed another inventory bug.
Items now drop around you if you are dropping an item and one is at your feet.
You may eat food now with the Quaff command. Food heals damage for now.
10:45 PM 11/23/05
Removed the console window.
Starting to add mouse support.
0.18e 2:33 PM 11/25/05
Monsters now have enchantment immunities.(can't be hit by a +1 weapon and so on)
Monsters now can be invisible(see invisible for monsters isn't implemented).
Fixed a bug in the Monster Generator.
Monsters can now regenerate.
0.18f 4:50 PM 11/28/05
Monsters can now use breath weapons.(Dragons and Others)
Item overlays can now add and take away from players speed.(+ and - to speed items)
Items can have see invisible.
See Invisible spell.
Changed Display slightly
Added Spells +/- ToHit, ToAC, ToDamage
Added item Slay (Creature Type) X4 damage
Added item Hurt (Creature Type) X3 damage
Added item Harm (Creature Type) X2 damage
Added Item Harm/Hurt/Slay Evil, THIS STACKS with the other damage bonuses
So if you have a "Holy Avenger" dagger that SLAYS DEMON and SLAYS EVIL
and you attack an EVIL DEMON it will do (X4 damage) X4
so lets say you do 2 base damage.
SLAY DEMON Raises that to 8 damage(2 X4)
SLAY EVIL Raises that to 32 Damage(8 x4)
So while a "Holy Avenger" is bad for evil monsters, it's REALLY bad for evil demons.
0.18g 4:04 PM 12/1/05
Added a MiniMap (works off the ~(tilde) key)*----Graphics only
Fixed an Inventory drop bug.
Monsters will now drop items.
Fixed a rather nasty bug(Out of bounds) in the dungeon display code.
The X key in the Inventory/Equipment Menu's allows you to examine Items.
If you are looking at Inv you can Examine Inv.
If you are looking at Eq you can examine Eq.
Works well for comparing items.
Fixed a few minor bugs.
Added Resting to regain 1 hp per turn(X key or 5 on num pad.)
0.19a 12:03 PM 12/3/05
Added Resistance (+/-) to specials.
Fixed a breathweapon bug.
Fixed an item drop bug.
Fixed a monster casting bug.
Added resist viewing to the View Player(C) menu.
Monster attacks can now drain experience and can poison.
Monsters now use an ammo variable.
Monsters that can heal other monsters will now do so.
Animals and Insects can't open doors anymore.
Made dungeon larger and added more monsters,Items, and item overlays.
Items now need to be identified.
Equipping an item automatically Id's it.
Examining an item also id's it(For now!!!!!!)
Added randomresist to special.txt parser.
Started work on skills.
0.19b 8:20 PM 12/5/05
Added wands
Added rods
Added spell effects for other items(rings,amulets and such)
Items will now stack and unstack according to thier stats.
Fixed a Targeting Bug.
Tweaked the Message parser a little.
You now can scribe spells into a spell book.
You now need a Mana crystal in your inventory to cast a spell from a spell book.
Mana crystal charges stack in inventory.(When you pick up a mana crystal it's charges
are add to the master crystal.I.E. you never have more than 1 crystal.)
Items will now cast a spell on a hit.(Fireball arrows and swords and such.)
SPACE clears the message display.
Melee and ranged skills have been implemented.
Magic skills have been implemented.(Except General Affinity)
I haven't completely abandoned ASCII but it doesn't work well anymore(will work on it later).
Changed experience(it now takes twice as much to level.)
Message's will now auto clear after four turns.
Item Specials that raise a skill level will now stack on the same item IE....
If you have an item that rasies Fire Affinity twice you will get
a 20% bonus instead of the normal 10% bonus!
Examining items shows relavent information. IE...(E(X)amining a shield won't show it's damage anymore(unless it adds to damage!)
---As of this writing this is what I have done for the newest build
0.19c 2:09 PM 12/13/05
Increased melee and bow skill leveling.
Fixed.. an inv drop bug.
Fixed.. Eq and Inv text weren't aligning correctly
Fixed.. There was a delay in monster movements that would stack and slow the game down,the delay has been removed
Mana crystals now display the charges they have when you open your inventory.
Added an equipment slot for spell books.
You must unequip a spellbook to (S)cribe spells into it.
You may now use the (M) key from the main screen to cast a spell from an equiped spellbook.
RDC styse messages (the old system was rather ugly)
I'm hoping to go to beta around christmas.....
Andrew
Needless to say Andrew has been very productive and busy since his last report. anothing I've noticed is that the projects are definitaly starting to evolve and mature. I'm assuming that soon, we'll all be busy giving atleast some of these games a try.
Barok, Ryan and Xerol essentially reported no progress this month. Of course that doesn't mean their project is dead, it is december after all, time for holiday planning and the rest of what we do during this month.
News Brief by MystikShadows
Have QB / FB news to report? Send an email to pberg1@gmail.com!
Gallery
Written by Pete / Lachie Dazdarian
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!
Mini Space Rogue by Lachie Dazdarian
Lachie is at it again -- this time with a new FB roguelike called "Mini Space Rogue" -- and boy, is it great so far! I was given a special sneak preview version of the game this month, and MSR is already a very polished and very fun game. It has many elements of traditional roguelike games, but many cool innovations too (such as attacking separately with your left and right hands). It certainly gets my seal of approval.
I would write a full preview for this game, but Lachie has been so kind to write his own preview the entire game for you -- and what better person to get the inside scoop on a game than from the creator himself?
-Pete
I've been developing a new game named Mini Space Rogue for the last 30 days which will be my entry for the Roguelike compo. The decision to work on a new project was quite sudden but once I started thinking about it I couldn't get it out of my head and had to start to develop it(I need help). Apologizes to people who are waiting for LONG to be released. My plan was to finish Mini Space Rogue before the December 16th(when I knew I'll be online) but I failed. I gave up a week before that date since I realized it couldn't be done. My concept simply turned out to be much tougher to code and the graphics more demanding to draw that I originally imaged it to be. I can't believe I convinced myself I could finish it before the 16th. But I must be honest, my work on the project was not very intensive with around 4 hours per day in average. I could only code during evenings since I was preparing an exam but a lot of time went into watching TV(my life is so exciting).
Anyway, Mini Space Rogue is a Roguelike game(what a shock) placed on an abandoned bio-research space ship and the movement is mock-tile by tile(characters slide from one position to another). Mini Space Rogue is also my first game done in 640*480 screen mode(weee!). NPCs and the main character are represented with a simple tile. No "walk" animations. A lot of time and effort went into creation of the game's interface which is both mouse and keyboard controlled(you pick). I think Mini Space Rogue will mostly be remembered because of it's interface. The battle system is turn-based(as well as the non-battle mode) and in the classic "you hit me, I hit you" concept I tried to introduce something new. You see, in Mini Space Rogue the main character can carry two weapons, one in the left hand and one in the right hand. During battle when you attack with one hand that hand stamina decreases and if it completely depletes your attacks with that hand will be less powerful. This concept is combined with the game featuring two types of weapons(hand and fire weapons) and with the main character being left or right handed(you pick). I was not quite successful there. The very system in not very beneficial for the gameplay but it doesn't damage it either. The game will feature 5 medium sized levels and one small(bridge). Being a Roguelike game it won't feature dialogues or some sort of plot development. It will be about exploring the ship, fighting monsters, leveling up and gathering useful items(a lot of items in the game). The in-game graphical design(map tiles) is not the game's strongest part but I managed to create a nice light/point of view effect. Sadly, this light concept created new problems since it requires 4 versions of each tile in the tileset to exist and the tilesets are being made with PP256. We all know about PP256 64 KB tileset limit.
Why it's called MINI Space Rogue? The original idea in my head included at least 5 huge space ships to explore featuring some neat way you find(track) abandoned space ships. If some game developer happens to really like Mini Space Rogue he or she(oh, yeah!) can try to expand it.
I need at least one more week to complete this game but great deal of it has been finished. The menus, instructions(it needs few more nitpicks), save/load game feature, entire interface, skeleton of the engine, 2.5 levels out of 6 and 90% of the graphics. All I need to do is design the remaining levels. It won't be easy but it will mostly be designing and very little coding. One more tileset probably needs to be created and there's the music. I think it won't be difficult to create nice music for this type of game. All I need is few Pads in Fruity Loops and viola! I have suspense-like atmosphere. Anyway, apologies to people who are waiting for my other projects to be finished(articles, QBasic Games Directory, LONG, ...). I just can't help myself(I'm sick).
I will be able to release the game somewhere in the middle of the January, 2006.
-Lachie Dazdarian
Visit Lachie's website, KENTAURI, to find his other games.
'apostrophe:
News From The QBasic Forum
Written by mennonite
new year edition, 2006
[issue 1]
|
|
= from the editor =
welcome to the first edition of 'apostrophe. this project began in response to a complaint made by pete berg, editor and host of qb express, the leading magazine on qbasic news: [yes, damnit, it's an excellent magazine. no, damnit, i'm not being patronizing -ed.]
As for 'The QBasic Forum," you complain that we don't include you in the Qmunity -- but it's for good reason, in my opinion: you keep to yourself and don't share anything with the rest of us.
'apostrophe is not intended to replace any feature of qbe, in fact it is designed as more of a supplement to qbe from our forum. there are at least three possible responses i expect and welcome from qbe and its readers:
- come here to read our news. it's certainly possible to do so, though it doesn't solve the "you never tell us" challenge.
- someone can pick up 'apostrophe and "transplant it" in whole or in part to qbe- i retain copyright as do the authors of things i quote and screenshot, etc... but i'm granting qbe the exclusive rights to copy/summarize/edit (please do not give us all the credit for your take on our articles) things from 'apostrophe for use at http://petesqbsite.com for the limited purpose of creating qbe articles, or for hosting copies of 'apostrophe at http://petesqbsite.com. be my guest, maybe i can even get someone i know to do this part for pete's sake.
- ignore us completely. when pete told me that we never update the rest of the community about what's happening here, i explained that for one, i don't think we're doing anything that anyone in the rest of the community really cares about. (imo.) we're not a development forum, we're mainly a help forum. some of us work on small projects of our own, but generally we're making demos and tutorials when others are making first person shooters in fb. etc. obviously, there are other help forums, too... and pete's is one. we tend to focus on it nearly to the absence of other topics, which we sort into... anyway, you've seen our forum.
there have been exceptions, of course. mac used to say the one exception was v'ger, a next-to-impossible ascii game whose code is so out of control that it may one day send cyborgs back in time to kill us.
lately there have been many other exceptions, and in the event that someone outside the forum is interested, i will attempt to tell you all you need or could want to know.
in regards to mark wilhelm's forum, while i consider our forum at network54 (the same forum that mallard put here for qbasic.com) to be "the qbasic forum", mark wilhelm decided he didn't like it, so he made... that. this is my own opinion, not shared by everyone on our forum, to be certain - but to me, we were and are the forum, not the "Classic Forum", and surely not the "old" forum. if someone wants to report on the news there, that is certainly their option. i don't as a habit go there, and i certainly don't post there. on the other hand, mark never comes here, either- but their news is "not my problem."
that said, i'll be doing my personal best to report our news (even news about myself) here with a professional "bias" or none at all. it certainly isn't possible for anyone to be bias-free, but then again - it is more than just possible to try. my opinions here will be announced as opinions, and hopefully the lesser of all features on the page.
'apostrophe will not be a monthly publication. it will be added to as often and inoften as i see fit. the latest news will appear at the top, with a dated heading- and older news, it would follow, (quite literally) that it be lower down on the page.
as you can see, i have made myself editor. i figured it was me, michael, or matthew - though there are other regulars that might care about this more than i do. both mentioned have websites of their own, and if one of them wants to take this project off my hands, i would be happy to link to them and step aside.
hopefully that takes care of any questions you have for now- we now return you to the news, which is already... in progress...
- mennonite
= kriegspiel referee =
trying his hand with an old development trick he worked at ibm, mac (yes, ibm-mac, har har) has led a handful of us into a chess project called "kriegspiel referee".
while we aren't interested at the moment in an ai that can play against the user, we are in the process of creating a computer chess game where two human players play chess against each other... without seeing his opponent.
because i enjoy the feeling of the wind in my hair, and because half of it goes right over my head, i will simply post a bit of what mac was trying to say about it, in his native danish tongue:
"For example in regular chess, assume that all opponent pieces are gone except for the King and you have a King and protected Pawn. If you are a good players, you know that if the opponent King is ahead of you, you can never promote (the opponent keeps moving to your side of the pawn). It is an agreed draw or else stalemate."
But in Kriegspiel, it is a win. You simply toss a coin and move to a random side. The opponent, sooner or later, moves to the wrong side and you advance!
On the other hand, in regular chess, if you are good players, you know that an end game of King-Knight-Bishop versus a King is a win. But in Kriegspiel, it is an obvious draw.
There is a third person involved: a Referee. This person keeps a third board with all pieces accurately placed. If it is White to move, White attempts to move and the Referee announces "not possible" until a legal move is made. Black hears this exchange and can sometimes guess what is going on. To avoid tricks, if White tries something like taking a White piece or moving a Pawn backwards, the Referee says "illegal move" so no bad data is transferred."
he then begins to outline our mission as coders, should we choose to accept it:
"The basic sequence is to identify a component of the system, such as LegalMove and develop a driver and simulation. Debug that first.
Then, in parallel without needing to communicate, the developer of LegalMove substitutes code for the simulation and the developer of the main display uses the simulation.
When both work perfectly, they are simply put in the same module and the program magically works.
Believe!
But you can't modify the driver or the simulation. They MUST be used as-is or integration will fail."
when i needed clarification, pete wrote a qb program to help break the language barrier. below is a screenshot: (it reminds me a lot of the danish translator i made a while ago...)
i can't say i've kept up with the project as much as i should have, but i know the board works and the logic "driver" (if i have half an idea what it is) is being worked on extensively by some of our best and brightest. the last time i saw the board, it looked like this:
yes, that's a cursor on row 2. we have a thing about ascii. we do graphics too, but i love ascii as much as anyone.
i personally denied myself a handful of opportunities for a full belly and an empty bladder to work on the intro screen. i did the layout yesterday or the day before (i don't really think in terms of "days", more like "uptime"...) and today i wrote the overly-functional menu code to run on top of it:
anyway, i'm very pleased. i can't wait to see more of this project complete, even less to figure out wtf it is!
[menn]
= computerghost's parents completely suck =
we won't be seeing much of computerghost for a while, his college grades are not completely up. mind you, cg is studying computers - good choice. his parents' answer to a round of bad grades?
show him what it's like now if he fails later.
instead of helping him in a more traditional fashion, cg's parents have decided the best course of action would be to do everything in their power to prevent his access to computers over the next year. obviously, he will need them in school to do his work, at home this simply won't be an option. this might not be so damning if cg lived at school- alas, he doesn't.
this might be the daftest thing i've heard in the course of my life, so to cg's parent's: a big "f-u" to the craziest effing morons i've ever heard of from the editor of 'apostrophe. you're both touched in the head.
i have hope- who knows? maybe they'll get brain transplants. we miss him terribly and hope to have him back soon.
[menn]
= mennonite's pretty good intro to qbasic =
i've been talking about this forever, so instead of just talking, i finally put it online. the thing is, it's been almost done for months, and i decided to just finished my work on chapter 4 and get on with it.
each chapter is a qbasic program. to view the tutorial, you run the program for the chapter you want in either the qbasic interpreter, or the quickbasic compiler. the rest of the chapters, 5 through 21, are still in the plaintext (included.) this is what the website means when it refers to "finished" vs. "unfinished", despite the fact that all 21 chapters are already available in one form or the other.
this is a very large tutorial i designed to replace an actual high-school level intro to programming class, and the plaintext of the tutorial as a whole would be about 70kb, roughly 1/5 to 1/4 the size of a plaintext copy of "the great gatsby". the project has already received mixed opinions from those i've shown it to, but i'm certainly very proud of it all the same. i intend to use it to teach qbasic to anyone i know who is interested in learning, and personally recommend it to anyone who is starting out, whether i knew them or not.
the download page is located on this site, click here if you would like to know more.
[menn]
= matthew's qbasic.com fundraiser =
by matthew
I have wanted to start fundraising to purchase QBasic.com from the first day Mark acquired it. I have finally gotten off my ass and done it. You can visit the fundraiser page here. I think I can do a better job at administering qbasic.com than mark can. The main features of the new site will be:
1) The Net54 forum will be the main forum(mark's forum at qbasic.plutokiss.com will remain linked to)
2) The site will be VERY open to suggestions
3) There will be a wiki installed somewhere so users can create/edit QB-related content in a section seperate from the main site
4) It won't look like dog diarrhea like the current site
5) I won't be mad with power when I acqure it :+)
I plan to make this a site for QB programmers, by QB programmers. This means I will not be greedy and not keep the site my own and only my own. The site will be very open to suggestions, and will include a wiki so people can create and edit content (in a seperate area of the main site) as they see fit. I will not leave FreeBASIC out of the site, although I won't focus on it either. I won't use a crappy content-management script (the only known non-commercial example of a good content-management-based site is Pete's QB site, so I don't want to take chances with making a shittier site than mark's.) The forum will be the net54 forum, like it used to be before mark threw it aside like it doesn't matter to anyone. I honestly think I can do a better job at it than mark could ever do.
If you are interested in donating, visit my fundraiser page, read it, and click the "paypal donate" button at the bottom.
[matt]
= other announcements =
from the programs you are proud of subforum:
computerghost - simple ascii space game (version 1.1)
solitaire - happy new year - times square program
kewbie - simple "mark-up type" text formatter - tformat.bas
until the next edition, happy coding :)
[2006 jan 02 issue 1]
Visit mennonite's site or The QBasic Forum.
Cadisman Game Review
A review by Stéphane Richard (Mystikshadows)
INTRODUCTION:
ON January 9th, inded005 announce, in this post
on the FreeBasic.net forum, that he converted an old QB game to FreeBasic. The game is called Cadisman and after taking a peek
at it in the provided link, I decided this was most definitaly game review material. I downloaded the game and started playing
it to get a feel of what the game is all about and well, let's just say this review was supposed to be done earlier than this. I got
caught in that game just a bit longer than I planned.
As usual, I will begin this review by talking a bit about the game and finish with the gaem review itself. So then, let's get right to
it shall we?
ABOUT CADISMAN:
CAdisman is a graphical RPG game and as such offers all the features one would expect of this category of game. It has a very decent
user interface an isn't all that hard to get into the game, even without instructions, and start finding your way around
the many locations and levels. Just to give you a bit of a preview, here are some screenshots taken from the website.
As you can see from this first screenshot right here, this game features one of the most detailed player profile
I've seen in a game. There's a lot of different characteristics of your player that changes as you gain
experience, fight battles and the likes.
This second screenshot features the very convincing tile graphics that make up the game. I particularly like the
many textures used in the game and the color selection is realistic.
This last screenshot is yet another example of the tile worksmanship. Even at this small size, inded005 really managed
to bring some excellent artwork to the game.
There are more graphics in the game as well, I'll let you play this game yourself so you can see them all as you make your
way through the game. And now, for the review. As always, I will review the game based on
playability, overall entertainment, replay value and technical feature.
PLAYABILITY: Score (4/5)
As I've said before, when you start the game, everything is quite self explanatory, the game is essentially played with the mouse an the
keyboard and as such, all the features of the game are readily available for you to use. A very intuitively designed icon menu on the right
gives access to such things as the player's profile, inventory items and the likes
in a very well presented fashion. As such I gave it a score of 4 out of 5.
OVERALL ENTERTAINEMENT: Score (4/5)
AS far as entertainement is concerned The game is quite entertaining, it features atleast a minimal enemy A.I. system based on the classic
turn based attack system. All in all, it brings the entertainement expected from this kind of game. I do wonder however if perhaps inded005,
now that the game is ported to FB, wouldn't be able to work with new gaming A.I. systems that might bring Cadisman
up yet another notch. All in all, it is a pretty good game so a 4 our 5 is very well warranted.
REPLAY VALUE: Score (3/5)
Again, Cadisman being an RPG, if you like RPG games you know the replay value of such a game. Since I haven't completed the game, I do not know if
the game can have aternate endings (other than either you succeed or you die). But hey, even that's already 2 possible endings right there.
I do believe however that the game has a good enough replay value to come back to it and finish it no matter how long it takes in my opinion. For
that reason, I gave it a replay value of 3 out of 5.
TECHNICAL FEATURES: Score (3/5)
By technical features I mean the amount of technology used to create the game. Although the game doesn't seem to have sound (I don't have a sound card at the moment but I haven't noticed any sound files) nor does it support Open GL or Direct-X
you can tell that alot of efforts have been made to bring the best gaming experience to the player with the technology that were used. Aside perhaps the characters of the game being a bit bigger, the game doesn't suffer in playability
regardless of the technology that was used to create it. For that reason, a 3 out of 5 is definitaly the score I give this category of review.
THE FINAL VERDICT: 14/20 (70%)
While playing the game for the little time I have played it, I found no big issue with it, everything seemed to be running quite smoothly and I came across no errors or complications. Just that is already a
big thing in my book. It seems to be a very stable game and from the little i've seen, seems to be a very addictive RPG. I just can't imagine any RPG lover out there not liking Cadisman. And for that, the score of 70% is more than well deserved.
I hope that inded005 can add many new adventures and twists to what seems to be an already complete adventure. A sequel would be a very
good idea in my book as well.
For those of you who want to give Cadisman a try, you can get it right here, if you like RPG games, you won't regret downloading this one.
MystikShadows
Stéphane Richard
srichard@adaworld.com
NPC Bad Guys in the New Age
Written by Nekrophidius
In times past, roleplaying games have almost always had good character development (I use the word "good", not "excellent"). The main character has always been portrayed in the best possible way by the storyteller. However, the "enemy", or "villian", has not been. This article is all about making that bad guy of yours just as important as the hero in your roleplaying game's story.
Gone are the days of "anonymous evil wizard kidnaps princess". Nowadays, players want to completely immerse themselves in the personalities of all the characters of a game. And for the most part, designers are certainly fufilling the needs. But what about on the other side? Why is there less attention payed to the one element which fuels the storyline to begin with: the antagonist?
Okay, so maybe you're reading this and wondering "why should the bad guy have his name in lights?". Villians, by their nature, are designed to be expendable. However, a well-designed villian will keep its purpose for a long time. Like so many things in the rpg storyline, the villian is a valuable tool. It's the fault of the villian that the world is gone crazy, or that the next city from here is on fire. What's going on?
The most effective way to begin the creation of your villian is to actually identify him or her. And I don't just mean "he's an evil wizard hell bent on ruling the world!". Well, maybe he is. Why? Did he get picked on in high school, and now he wants revenge against his torturers? Maybe he got stood up for the prom or something. In any event, there must be a reason for his mission. After all, the "good guy" has a reason for HIS mission, why doesn't the bad guy?
Okay, let's assume your all-powerful evil wizard has a hatred for fluffy bunnies. Let's say the main character loves fluffy bunnies and wants to protect them all. So, now there's a purpose for the evil wizard's "madness". It may be silly, but it's more than 99% of the bad guys out there. Why does he hate fluffy bunnies? Hrm. Maybe he got bitten by one as a child and grew to hate them. Maybe he thinks fluffy ones are ugly, preferring the shaved ones (so maybe he's going around shaving all the fluffy bunnies). Maybe in his quest to rid the world of fluffy bunnies, he runs into something which likes the fluffy bunnies and tries to help them out. Now, the evil wizard guy has another enemy! So now he's going to hate whatever it is that helps the bunnies (maybe...two- tailed deer? Okay, works for me). So now, we've got an evil wizard who hates fluffy bunnies and two-tailed deer. Now we're getting somewhere, our bad guy has a purpose in life, which is to hunt down fluffy bunnies and two-tailed deer.
Is the evil wizard going to torch an entire town because of his hatred for fluffy bunnies? Probably not, unless it was populated by fluffy bunnies (or environmentalists, take your pick). As insane as people get, there are just certain things that do not make sense. The bad guy's actions should reflect his motivation. No action should be "just coz he's evil", that's dull. He should go around putting fluffy bunny's heads on pikes, kinda like shown in the ending of DOOM. Now that's true evil (and a fitting representation of his hatred for fluffy bunnies).
Now, how does the main character even find out about the bad guy's mission? Does he read it in the latest issue of "Villian Digest"? Probably not. Perhaps the hero had a bunny, and the evil wizard guy took his bunny away, so now the hero's pissed. Or maybe the hero's girlfriend has a bunny that was taken. Whatever the case is, the hero has to be informed of the bad guy's actions somehow. After all, this is what sets him out on his journey to begin with. Make it believable...and sensible!
So, we've established that the bad guy hates bunnies. Okay. So now, what does the bad guy LIKE? I hear dozens of groans right about now, with the same thing: "oh man, who cares? it's the bad guy, who gives a rat about what kind of person he is". Wrong! The player cares! Does the villian like music? What kind? How about flowers? Sure, it seems crazy for the bad guy to like flowers, doesn't it? But it isn't crazy. I mean after all, everyone has likes and dislikes. Maybe the bad guy likes this one flower which grows only by this one certain pond. Hell, maybe the bad guy likes spending time by the pond in the evening, watching the sun set in the presence of his favourite flower. I'll make a case in point here...if you've played "Lunar Silver Star Story" on the Playstation console, the main villian, Ghaleon, had a love for music, and even played a musical instrument.
Well then, another set of details come to mind here. Where does the bad guy live? Sure, you can be cliche and say "a big castle atop of a mountain with a skull carved into the side!". ****snore**** been there, done that, got the t-shirt. Okay, so maybe you really do want a castle for the bad guy. How'd he get it? Did he just magically make it appear out of nowhere? Wouldn't the locals get kinda pissed about that? Even in rpgs, there are laws! I'd have to say that making a castle just sit down anywhere has got to be against someone's laws. So, how did he get it? Maybe he inherited it. Maybe he paid for it himself. If so, how'd he get the money? What does he do for work? Is he only a bad guy during his time off from his job? If he doesn't work anymore, did he get fired for his obsession with bunnies? Maybe he missed too many days of work chasing down the critters, got fired, and now he's really mad. "Damn bunnies are ruining my life! They must PAY!" So now, he's in danger of losing his castle, since he has no income and can't pay the taxes or whatever. Okay, mad killing spree! Not. How is a mad killing spree going to help things? Think about it. Well, maybe if he finds enough fluffy bunnies, he can just sell their fur or something. Just to make some money to keep his pad, while at the same time, ridding the world of these "gruesome furry monsters". Although the thought of the bad guy just going postal is kinda cool, it's an overused cliche that should be avoided unless absolutely necessary.
I think by now you're beginning to understand the importance of the bad guy's character development. But there's just a few more things I'd like to cover before I call this a wrap. First of all, we've established that our bad guy is a big evil wizard. Now, how did he become a wizard anyways? Did he go to school for it? Who were his teachers? What do they think of him now that he's a big bad bunny slayer? Do they look at his yearbook picture and shake their head in disbelief? And what about his parents? Maybe his parents sent him to magic school as a punishment for his arsonistic obsessions. Yes, antagonists can have more than one obsession, in fact, the more the merrier. Well, now the evil wizard is all powerful, and comes back to punish his ungrateful parents for their "cruel treatment". And while he's at it...he eats their bunnies.
Second of all, eventually the bad guy and the good guy are going to cross paths, you can't avoid this. Let's say the good guy is travelling with a cute chick. The bad guy sees her and falls in love with her. He forgets his obsession with bunny murder and relentlessly pursues the good girl. Well, now we've reached a dilemna...is he still a bad guy? C'mon, bad guys are sposed to be BAD! They aren't supposed to have emotions! Right? Right? Wrong. It's no mystery that opposites attract. And what if the good girl suddenly develops a crush on the bad guy? What if the bad guy has no interest in her? hrm...imagine the problems that can arise in this situation. And right there, you've got a vehicle for creating a storyline within a storyline. Now, what happens if the bad guy and the good girl both fall in love with each other, and the good girl betrays the hero? Is the former good girl suddenly a menacing legion of doom? Maybe, maybe not, that's up to you to decide. BUT! It doesn't have to be that way. Most people just automatically assume that just because the good girl has gone astray that she's now evil too. Bad assumption. Downright evil, even.
The final consideration is the end of the villian. Does the villian die in the end? Usually. But does this have to happen? I mean after all, all we're trying to do is stop him from doing what he's doing. What if we were to convert him? Make him see the error of his ways? Let him know that his bunny murder is breaking the hearts of hot sexy women everywhere? Okay, maybe he repents. Now, the hero puts a knife in his head. HAHAHA! Now who's the bad guy, biatch! *cough* Anyways...consider the end of the story. If you deem that the antagonist must die, it must be for a very good reason. And again, don't fall back on "coz he's evil". After all, killing in itself is a necessary evil, and makes the hero no more a good guy than the bad guy. But once you balance the WHY, you'll know what you have to do to end the story. But consider this one final point. There is no better way to vanquish an enemy than to make him an ally. You'll avoid that one final killing and you'll accomplish your goal all at once. Of course, at the same time, nothing beats a good bloodbath of a final battle, good versus evil!
If you've absorbed even half of what I've outlayed here today, you're off to a good start at developing excellent villians. If you're one of those AD&D players (as many RPG developers are...or were), I recommend reading Kirk Botula's excellent "Complete Book Of Villians" (ISBN 1-56076-837-1), as it goes into much more detail of the concepts I've covered here. Just say NO! to cliche bad guys!
"Virtue untested is innocence." -Anonymous
Download a copy of this article: npc_bad_guys.txt
SmithcoSoft Map Editor Preview
Written by SmithcoSoft Creations 2002-2005
Description
SmithcoSoft MapEd is being designed for the use of map
creation for RPG games. Specifically it is being designed
for a SmithcoSoft Creations upcoming RPG, which will
not be announced at this time. The Editor has many useful
features including many that most map editors do not have.
The editor is being developed using SDL but can be used
to make maps for any 2D engine, as the files saved are
simple data. Though it is not yet complete it is nearing
completion, and a demo or full versions should become
available soon.
Features
Standard Map Functions
- Load Map
- Save Map
- New Map
- Fill Map
- Tile copy
- Load Tileset
- Take Screenshot
Layer System
- 5 visible layers
- Background
- Base
- Object
- Fringe
- Foreground
Graphics Loading
- Can load multiple tilesheets into a single array,
images per tilesheet must be the same size, but
different tilesheets can have different sized tiles.
- Can load any sized tile sheet or tile image.
Scripting
- Scripting is built into the editor and allows a variety
of effects or options, upon release the code will be
available for other users to use those effects.
- Can save, load, and edit map trigger lists, and scripting
files.
- Trigger locations can be viewed on the map
- Triggers will be initialized in game by either
contact or direct interaction, quite often triggers
will be used for loading of new maps and transitions.
- The list viewed in the pictures is by far not complete
of all of the scripting abilities.
Character Editor (yet to be added)
- Will allow for editing of character data files,
a character graphic will be placed on the base layer
where you can add text options or move options
just as with the scripting.
-
- You can specify the route an NPC will take or give
the character a bounding box to roam freely.
- You can also choose the method of interaction, be it
contact or by talking to the character directly.
Animation editor (Yet to be added)
- Will allow creation of data files specifying which
tiles on the map will be animated and to which other
tiles they animate. This will save code and time in
the main code of the game.
Menu System
- The MapEd menu system is fully dynamic and will
conform to meet the text options in that specific
menu.
- Though simple in looks the menu system is quite
a power option for the editor, similar code will
go into the actual game for such options.
MiniMap
- The mini map is used to view the entire map in a
relatively small area, though buggy on resizing yet
it serves its purpose.
- Users can customize how the mini map looks by editing
the mini map file(s). Each tile is represented by a
single color specified in the data files.
Environment
- The editor is set up to run in 1024x768 in any bpp
mode the users wants, however the maximum editing
area is 800x600 as the rest is used up by menus and
map info.
- Although default map area is currently 800x600
any size map can be used up to that size. So say your
want to use 320x200, or 640x480, or even 111x222
then that's what it will be set to. You can also get
an editing size than can show 1 full screen shot of
your map, so you know exactly where everything is
before you even test the map in game.
The following pictures will briefly show some of the
features of the editor, just keep in mind these are
placeholder graphics =)
This is the default load of the MapEd
This is the fill screen option before and after
This is showing the base layer with a small scene I created
to show how it looks while creating the maps.
Same view as above with the mini map turned on
This is the object layer overlaid on the base layer
(note the background of the tree is transparent)
This is the fringe layer overlaid on the object and fringe layers
This is the main menu
This is before and after of a saved map
(note uses custom text handling for text input)
Here are just a few of the scripting menus
And finally here is how the triggers will appear on the map
Comments
There are other features I have not listed here today,
but what I have listed is being developed now.
Also I am looking for a good artist for my upcoming
game which uses a slightly altered version of the
MapEd engine which gives a smooth pixelxpixel scroll
using SDL, and the many other game effects I am and
already have developed. I am willing to work with the
artist on sizes and styles. The story for the game is
more or less complete and the engine is almost ready
to go, just as soon as the map editor is finished.
If anyone is at all interested let me know, and i'll
fill you in on the details. Questions are welcome as well.
Email me at smithcosoft@yahoo.com
AIM me at smithcosoft
or just PM me at http://forum.qbasicnews.com
Monthly Awards
Written by Pete
Every month, QB Express hands out two awards to recognize QB or FB coders and websites that have done exceptional work in the last month. They are not awarded for work done in the past, only for work that has been released since the last issue of the magazine. We will bring you these awards on a monthly basis to help give credit where credit is due.
Site of the Month
QB Top 50
http://www.qbtop50.com
Webmaster: AhmedF
Way back in Issue #5 of QB Express, I wrote up a Blast From The Past article on the history of QB Top Sites lists and their influence on the QB community. I trumpeted the importance of QB top sites lists, because back in the golden age of QB on the Internet (ie: 1998), they brought the Qmunity together. Here's a snippet from that Blast From The Past article:
Back in QB's earlier days on the web, there were literally hundreds of QB sites all over the place, and it was pretty much impossible to keep track of them all. The best method anybody found were the anarchic top sites pages where webmasters could automatically add and promote their sites (without going through a middleman webmaster). Top sites pages like the original QBasic / QuickBasic Top 50 were extremely important to the QB community for sharing and promoting sites that would have otherwise been hidden away in the dark corners of the world wide web, never to be visited.
When AhmedF re-launched the QB Top 50, I was very excited. It's been years since there was a legitimate QB top sites list (the QB RPG Top 50 was devoted to only RPG sites, easily spammable and full of broken links). And for the first time in history, AhmedF has set up a fair and difficult-to-cheat top sites script that rates based solely on unique hits to your website. Judging by its success in just the first few weeks of existence, the QB Top 50 will become another new central hub for the Qmunity.
For its great design and potential to bring the far corners of the Qmunity closer together, the QB Top 50 is the QB Express site of the month!
Programmer of the Month
marzec
(Mario Zechner)
http://goddess.selfip.com/yagl
Up in the News Briefs section, marzec announced his new library YAGL - Yet Another Game Library, but judging by its humble title and the humble way he pitched it, you would never guessed that this library is absolutely genius. In just a month, YAGL has repeatedly wowed the FB community with its "blazingly fast" speed and features. Several people have released demos taking advantage of YAGL, and they are extremely impressive. Z!re has released several graphics demos AND switched her sprawling RPG, Fieldview to YAGL. Nekrophidius has gotten behind YAGL big time, and is promoting it all over the place and developing in it himself. He even made this banner ad to help promote YAGL:
After you check out the YAGL Official Site, check out this Freebasic.net post where marzec originally announced the library and he posted his early dev log. And then -- most importantly -- check out this page which features several awesome projects created in YAGL. Here are a few of the cooler ones:
Three of these screenshots are from graphics demos by Z!re, and the fourth is from the mini game Asteroids 3D which was coded for a 48h challenge. You can check out all of these programs at the YAGL Projects page.
For making such an awesome graphics / game library, marzec is unquestionably the QB Express programmer of the month!
Have a suggestion for Programmer / Site of the Month? Email me!
Comics
By Rattrapmax6
Rattrapmax6 is back this month with another QBasic Horse Humor comic!
Tree Tutorial, Parts 1 & 2
Written by Syn9
Introduction:
This tutorial is designed for someone with a small background in 3d matrix math and preferably with experience dealing with child-parent relationships within objects. A good example of this type of relationship would be skeletal systems.
There are 6 parts covering everything from setting up the software 3d development scene to displaying our final tree in an OpenGL scene. We'll be covering Parts 1 and 2 in this issue.
- Part 1: 'Base Code': Providing the base code for a simple 3d scene.
- Part 2: 'Planning': The makeup of a tree and how we plan to display our end product.
- Part 3: 'Branch Skeleton': Development of our branch system to make a very basic display of a parent-child skeletal system that will become our tree.
- Part 4: 'Leaf Planes': Creation of our leaf planes.
- Part 5: 'Branch Skinning': Skinning our tree skeleton and saving the mesh information
- Part 6: 'Final OpenGL Scene': Creating the OpenGL scene to display our mesh
Part 1: 'Base Code'
In order to properly see all the branches we must setup a 3d scene that we can change our viewing angle of. We'll also be able to Zoom in & out of the scene to aid in viewing the entire tree.
The following code will establish a software 3d environment showing a pixel grid floor. This grid consists of points on the X and Z axis with a 0 y coordinate. We will be constructing our tree to stick out of this floor by moving + on the y axis.
3dscene.bas:
DECLARE SUB getXY (x0!, y0!, z0!, sx%, sy%)
DECLARE SUB mRotate (an!, plane%)
DECLARE SUB mMult ()
DECLARE SUB mIdentity ()
declare sub mScale (factor!)
DEFINT A-Z
randomize timer
const xplane = 0, yplane = 1, zplane = 2
DIM SHARED apage, bpage, zback, rad as single
DIM SHARED matrix(8) AS SINGLE, tempmatrix(2, 8) AS SINGLE
screen 13,,2
apage = 0
bpage = 1
rad = 3.141592 / 180
zback = 30
matrixScale! = .8
xan! = -20
rotSpd! = .05
scaleSpd! = .001
DO
swap apage, bpage
screenset apage, bpage
cls
mIdentity
mRotate yan!, yplane
mRotate xan!, xplane
mScale matrixScale!
FOR x! = -10 TO 10 STEP 2
FOR z! = -10 TO 10 STEP 2
getXY x!, 0, z!, sx, sy
PSET (sx, sy), 7
NEXT
NEXT
if multikey(&h1) then exit do
if multikey(&h48) then xan! = xan! + rotSpd!
if multikey(&h50) then xan! = xan! - rotSpd!
if multikey(&h4b) then yan! = yan! - rotSpd!
if multikey(&h4d) then yan! = yan! + rotSpd!
if multikey(&h4e) then matrixScale! = matrixScale! + scaleSpd!
if multikey(&h4a) then matrixScale! = matrixScale! - scaleSpd!
while inkey$ <> "": wend
LOOP
SUB getXY (x0!, y0!, z0!, sx, sy)
nx! = x0! * matrix(0) + y0! * matrix(3) + z0! * matrix(6)
ny! = x0! * matrix(1) + y0! * matrix(4) + z0! * matrix(7)
nz! = x0! * matrix(2) + y0! * matrix(5) + z0! * matrix(8) - zback
IF nz! = 0 THEN nz! = -.1
sx = 160 + nx! / nz! * 256
sy = 150 + ny! / nz! * 256
END SUB
SUB mIdentity
for i = 0 to 8
matrix(i) = 0
NEXT
matrix(0) = 1
matrix(4) = 1
matrix(8) = 1
END SUB
SUB mMult
FOR i = 0 TO 8
tempmatrix(0, i) = matrix(i)
NEXT
FOR y = 0 TO 2
FOR x = 0 TO 2
v! = 0
FOR a = 0 TO 2
i1 = y * 3 + a
i2 = a * 3 + x
v! = v! + tempmatrix(0, i1) * tempmatrix(1, i2)
NEXT
i3 = y * 3 + x
matrix(i3) = v!
NEXT
NEXT
END SUB
SUB mRotate (an!, plane)
SELECT CASE plane
CASE xplane
tempmatrix(1, 0) = 1
tempmatrix(1, 1) = 0
tempmatrix(1, 2) = 0
tempmatrix(1, 3) = 0
tempmatrix(1, 4) = COS(rad * an!)
tempmatrix(1, 5) = -SIN(rad * an!)
tempmatrix(1, 6) = 0
tempmatrix(1, 7) = SIN(rad * an!)
tempmatrix(1, 8) = COS(rad * an!)
mMult
CASE yplane
tempmatrix(1, 0) = COS(rad * an!)
tempmatrix(1, 1) = 0
tempmatrix(1, 2) = SIN(rad * an!)
tempmatrix(1, 3) = 0
tempmatrix(1, 4) = 1
tempmatrix(1, 5) = 0
tempmatrix(1, 6) = -SIN(rad * an!)
tempmatrix(1, 7) = 0
tempmatrix(1, 8) = COS(rad * an!)
mMult
CASE zplane
tempmatrix(1, 0) = COS(rad * an!)
tempmatrix(1, 1) = SIN(rad * an!)
tempmatrix(1, 2) = 0
tempmatrix(1, 3) = -SIN(rad * an!)
tempmatrix(1, 4) = COS(rad * an!)
tempmatrix(1, 5) = 0
tempmatrix(1, 6) = 0
tempmatrix(1, 7) = 0
tempmatrix(1, 8) = 1
mMult
END SELECT
END SUB
sub mScale (factor!)
for i = 0 to 8
matrix(i) = matrix(i) * factor!
next
end sub
CONTROLS:
Rotate scene: arrow keys
Scale scene: +/-
I will only provide a simple explanation on the functions of this code that will directly affect our progress later
mIdentity
mRotate yan!, yplane
mRotate xan!, xplane
mScale matrixScale!
These commands will setup our matrix to properly convert 3d coordinates to our rotated and scaled view
getXY x!, 0, z!, sx, sy
PSET (sx, sy), 7
getXY will multiply our 3d coordinate by our matrix and spit out a screen coordinate which Pset draws
if multikey(&h1) then exit do
if multikey(&h48) then xan! = xan! + rotSpd!
if multikey(&h50) then xan! = xan! - rotSpd!
if multikey(&h4b) then yan! = yan! - rotSpd!
if multikey(&h4d) then yan! = yan! + rotSpd!
if multikey(&h4e) then matrixScale! = matrixScale! + scaleSpd!
if multikey(&h4a) then matrixScale! = matrixScale! - scaleSpd!
while inkey$ <> "": wend
We will be using multikey extensively since it provides a much faster response time than inkey$. the last line clears the keyboard buffer so that on our next cycle we detect only new keys that were pressed for that cycle.
I wont be explaining how the 3d math functions work to save writing, but if at the current time you do not understand the theory behind 3d matrix math I highly recommend doing some research on the subject. Rel has written some awesome tutorials that you can find here http://rel.betterwebber.com/junk.php?id=21
Part 2: 'Planning'
Branches:
The Idea is to have a branch made up of several segments. At any of the segments a new branch can be attached. The further you get away from the base of the branch the smaller the diameter of the branch and length of each segment become. Also, the base of a branch will start out at the diameter of the point that it is connected to. Lastly, since we don't want a really long branch to have a base at a point toward the end of a branch, we'll limit the number segments that a branch can have based on what segment its base is connected to
Leaves:
The leaves are made up of flat squares that are displayed over the branches. The center of each plane is positioned around a random joint on a random branch. The plane will be placed at a point that is > 1/2 along the branches to ensure that the leaves are in the upper part of the tree and not on the trunk. Next, the plane is rotated opposite the direction of the object and camera in order to make them constantly face forward. Then once the engine is displaying the tree in openGL, the leaves will be z-sorted and blended together.
I hope I didn't lose anyone. Just incase, here is a picture to hopefully give a good visual representation.
End Product:
For the final mesh, we will make a 'skin' around the branch skeleton by finding points that are perpendicular to each segment connection, then draw a cylinder connecting each segment. At the base, instead of a cylinder we'll have the 1st segment's cylinder come to a point to make a cone. These cones will be stuck into the parent branch segment base point. In order to make the polygons display properly in openGL we'll also generate UV coordinates and Normal vectors for each vertex.
Download a copy of this tutorial: treetutorialpt1-2.zip
Dynamic Arrays Inside a Type
Written by Deleter
Amazingly enough, I finally figured something out so that I can write something other than a rant! In this somewhat off color tutorial by one of the qmunities more random individuals, I explore a somewhat interesting and highly useful technique for making a dynamic sized array inside a type.
This requires more doing than a normal array since you cannot use redim on a type, it just doesn’t work.
For this tutorial, you are going to have to understand pointers, if you don’t you can still follow along, but it might not make sense.
To start us off, lets make our own user defined type. (UDT):
type MyType
x as byte ptr
end type
Ok, now that we have a type, we have to declare a variable with it:
dim as MyType myVar
Now, we want to create an array for usage later on in the program. This introduces the callocate command. For those not familiar, callocate allocates a number of bytes and erases them (allocate simply allocates them). Creation is done as follows:
myVar.x = callocate(bytes)
Callocate creates an area of memory of size bytes and then hands the address over to our pointer. Now, to use this array, we can access it in the following way:
myVar.x[1]=42
Ok, that’s all!
No? More you say? Alright, let's go!
The above example was great, assuming you only want an array declared once and wanted only byte elements, we can do a heck of a lot more than this, so lets do it.
Let's say we allocate the array, but then realize later on we need more space. This can easy be done with the reallocate command:
myVar.x = reallocate(myVar.x, newBytes)
In this, we remake the array so that it now contains an amount newBytes of, erm, new bytes. Luckily for us, v1ctor has made the command as easy as possible, so the old contents are not erased and your data is safe when resizing the array (that is assuming your new size is the same or bigger size).
Once we are done with the array, use the deallocate command to free up the memory. It is done automatically and the end of the program, but its better practice to do it manually so you don’t end up with memory leaks:
deallocate(myVar.x)
Now we can make, resize, and delete our array, but how do we make one whose elements are bigger than a byte? Lets do this with integers first. An integer in freebasic consists of four bytes put together. Therefore for each element of our array, we need four bytes instead of one. To start us off, we need to change our UDT so that it is an integer pointer instead:
type MyType
x as integer ptr
end type
Now, when we create it, we have to replace the implied * 1 with a *4:
myVar.x = callocate(elements * 4)
Where elements is the amount of elements we want in our new array. Likewise, to resize our array, we have to also use a * 4:
myVar.x = reallocate( myVar.x, newElements * 4)
Where newElements is the amount of total elements we wish to have. To access it, luckily we do not have to worry about bytes thanks to the fact we are dealing with an integer pointer. This automatically splits the memory up for us for access. So, access to the first, second, and third array elements would be as follows:
myVar.x[0]=42
myVar.x[1]=1764
myVar.x[2]=84
Now that we have the basics of allocating and reallocating based on a known bytesize, its time to figure out how based on an unknown size. For this, the command sizeof( type ) is used. If you two haven’t met, sizeof, programmer; programmer, sizeof. Ok, here is the usage of sizeof:
print sizeof(integer)
As you will see if you run this program, you will get the number 4. That is because sizeof returns the number of bytes a type needs. To apply this to our earlier code, we can do the following:
myVar.x = callocate(elements * sizeof(type) )
Where elements is the amout of elements you want for your array type. As you may have caught on, guessed, or otherwise figured out, this can be extended to UDT’s for some really sweet applications. Example:
‘create a type for usage in another type
type MySubType
x as integer
y as integer
end type
‘create a type for “owning” another type
type MyMasterType
mySub as MySubType ptr
end type
‘make a variable of the “owning” type
dim as MyMasterType myVar
‘used to define number of elements, not necessary, used for clarity
dim as integer elements
‘set for amount of elements you want in array
elements = 10
’allocate the memory
myVar.mySub = callocate( elements * sizeof(MySubType) )
‘first array element
myVar.mySub[0].x = 21
myVar.mySub[0].y = 2
‘... other elements can be referenced here...
‘last array element
myVar.mySub[9].x = 84
myVar.mySub[9].y = 12
‘add one to number of elements
elements +=1
‘resize array to include new element
myVar.mySub = reallocate( myVar.mySub, elements * sizeof( MySubType ) )
‘check and see that old values have not been erased
print myVar.mySub[0].x; myVar.mySub[0].y
print myVar.mySub[9].x; myVar.mySub[9].y
‘new array element
myVar.mySub[10].x = (42 or 7)
myVar.mySub[10].y = 3
‘show new array elements
print myVar.mySub[10].x; myVar.mySub[10].y
‘free up the memory, we are done with it
deallocate(myVar.mySub)
sleep
end
This example contains all the ideas presented in this tutorial, so if it seems overwhelming at first, go from the top and go step by step, I commented everything so that you can understand it better.
That is all for now. With this knowledge, go forth and use memory with confidence, it’s a powerful tool. Thanks for reading.
-Deleter
Download a copy of this tutorial: Dynamic_Arrays_Tutorial.doc
Music Tutorial Part 1
Written by The Awakened
I needed a break from C++ tutorials, so I figured I'd write about something I'm a little more proficient with: music. The method I'm going to teach you isn't exactly "standard", but it definately gets you on track as soon as possible. I know many people might want to use a tracker or sequencer, but don't know much about music theory and whatnot. Hopefully, I can help you out.
I highly recommend learning an instrument, and guitar and piano are among the more "all-encompassing" instruments, meaning that most of the stuff taught here can be applied to either of those instruments.
For the theory that I teach, I'm not exactly a conservatory student, although I know quite a bit. I'm not 100% on the staff and "official names" for certain things, but when it comes to scales and chords (which, in my opinion, is where it really counts), I'm fairly proficient. I've met people in my school who've been playing piano for a few years longer than I have at guitar (they've been taught by the Conservatory, and I'm pretty much self taught), and I ask something like "what's the relative mixolydian of G?", and they immediately go cry in a corner. Something that might take me 10 or 15 seconds to figure out, and they have no idea.
Anyway, enough of me speaking highly of myself. ;) Let's get going.
1. Notes
In western music, we have 12 notes. They are:
A, A#/Bb, B, C, C#/Db, D, D#/Eb, E, F, F#/Gb, G, G#/Ab. Then it repeats. A, A#/Bb...
# means "sharp", b means "flat". Notice the ones with flat and sharp signs. They're the same note, but you can refer to them in two different ways. A# and Bb are the same note. Also notice that some notes don't have flats and sharps. B doesn't have a sharp, and C doesn't have a flat. Same with E and F.
Now, most contemporary music doesn't use all these notes in one melody. Instead, we use patterns of notes called scales. The most common scale is the major scale. Starting with C, it looks like this:
C, D, E, F, G, A, B (and repeat)
Wow. That's cool. Compare it to the 12 notes above, and you'll see there's a pattern. It starts on C, then it goes up in different "intervals." When it jumps by two notes, (like say, A to B), it's called a "whole step." If it's only one note (for example, A to A#), then it's called a "half step." The intervals of the major scale are as follows:
Whole step, whole step, half step, whole step, whole step, whole step, half step.
The half steps are in between E and F, and B and C. That's why it's easiest to remember the C major scale, since the half steps and whole steps are already built into the western 12 note system.
2. Keys
When someone refers to the "key" of the music, they're referring to what the main note that the song uses and keeps "returning to", and what scale is being used. As we saw above, the most basic scale is the major scale, and the simplest key to have the major scale in is C (simply because there's no sharps or flats to deal with). But having many different songs in the same key gets boring. Let's look at the major scale in a few different keys. Remember, we use the whole-whole-half-etc pattern.
In E:
E, F#, G#, A, B, C#, D#
In A#:
A#, C, D, D#, F, G, A
Try figuring out a couple more for yourself.
Easy enough? Good.
3. Diatonic Scales
A diatonic scale is a seven note scale. The most common is the major scale. Scales are notated as follows. Let's take the C major scale:
C, D, E, F, G, A, B
1, 2, 3, 4, 5, 6, 7
1 is your root, 2 is the second, 3 is third, etc. So C is the root, D is the second, E is the third, and so on.
Now, the major scale is your all out, super happy, bouncy bubbly scale. But how about some other patterns of notes? How about some more scales?
If you're thinking "oh crap, he's gonna give me some more long patterns to memorize!!!", then calm down. Let's look at the C major scale again.
C, D, E, F, G, A, B
What if I kept that pattern, but I started on a different note of the seven note scale?
D, E, F, G, A, B, C
Ooh! Sounds interesting, kinda rockin'. How about another one?
E, F, B, A, B, C, D
Hmm... kind of mysterious... interesting, could make some pretty heavy riffs.
It doesn't have to be done on the C major scale (duh), you can do it to other keys as well.
E, F#, G#, A, B, C#, D#
can become
F#, G#, A, B, C#, D#, E (I just shifted up by one note of the original scale)
These are called the "modes" of the major scale. In C major, C is the "root mode". There are names for the other modes too:
1 - Ionian (Major)
2 - Dorian
3 - Phrygian
4 - Lydian
5 - Mixolydian
6 - Aeolean (Minor)
7 - Locrian
These are Greek names. I know it's a bit much to take in all at once, but let me try to explain the overall sound and feeling of each one:
- Ionian - Happy, triumphant. Most happy pop songs are in the Ionian mode.
- Dorian - Laid back, cool, rockin'.
- Phrygian - Slightly mysterious, sad.
- Lydian - Happy, but mysterious. It smiles at you with it's eyebrow raised...
- Mixolydian - Happy, but not quite as happy as the Ionian mode. More rockin'.
- Aeolean - Minor scale. Sad, emotional.
- Locrian - Mysterious and angry.
So the one I did above with the C major scale was:
D, E, F, G, A, B, C
That's D dorian. If I started on E, it would be E phrygian. And this can be done in any key, as long as you know what notes are in the major scale. Easy enough? Sweet.
4. Intervals and Harmony
Playing up and down the scale can get boring, if you're only playing the notes in sequence. This is where intervals come in. An interval is the "distance" between two notes. I've put how many half steps away from the root the interval is.
0 - Root
1 - Minor Second
2 - Major Second
3 - Minor Third
4 - Major Third
5 - Perfect Fourth
6 - Augmented Fourth/Diminished Fifth
7 - Perfect Fifth
8 - Minor Sixth
9 - Major Sixth
10 - Minor Seventh
11 - Major Seventh
12 - Octave
Note that this isn't necessarily relative to the key you're playing in. It's relative to any note.
Two notes that are an octave apart are the same note, just one whole register higher.
Notice something. We've got something called a "perfect fifth", yet it's 7 half steps away. Why? Because in the diatonic scale, it's five steps away. See, every mode of the diatonic scale is made up of different sequences of these intervals. When you begin to compose your own stuff, you can hear how each interval sounds in a scale, and step outside the scale when you want to, and make it sound cool.
Harmony is two or more notes played at the same time. You can play these intervals at the same time, and depending on what intervals you play, they can sound pleasant, or gut-wrenching. :)
If you look at a scale, the harmony is "built in" for you. Just play two or more notes of a scale at the same time and you've got harmony. Sometimes it sounds good, sometimes it doesn't. How will you know when they sound good? Let's look at arpeggios.
5. Arpeggios and Chords
Arpeggios are simply a group of three or more notes that are spaced out a bit more than scales are, and played as individual notes (as opposed to chords, as we'll see in a bit here.) The most common and simple ones are 3 note ones (also known as triads), and out of the 3 note arpeggios, the most basic ones are Major, Minor, and Diminished.
Major:
Root, Major Third, Perfect Fifth
Minor:
Root, Minor Third, Perfect Fifth
Diminished:
Root, Minor Third, Diminished Fifth
A C major arpeggio would look like:
C, E, G
Because E is a major third away from C, and G is a perfect fifth away from C.
An A minor arpeggio would look like:
A, C, E
Because C is a minor third away from A, and E is a perfect fifth away from A.
A B diminished arpeggio would look like:
B, D, F
Because D is a minor third away from B, and F is a diminished fifth away from B.
How does all of this fit together? Well, with the way the diatonic scale is set up, different notes have different arpeggios associated with them. Taking a look at the C major scale again:
C, D, E, F, G, A, B
If we started with C, and made a 3 note arpeggio by going up by two notes, we'd get:
C, E, G
Major arpeggio, just like the above. Do the same with D:
D, F, A
It's a minor arpeggio. E:
E, G, B
Another minor arpeggio. "Okay, is there a pattern?" Yup. Before I show you, see if you can figure out, by yourself, the order of what types of arpeggios are in the major scale.
And here's the pattern, with the C major scale as reference:
C, D, E, F, G, A, B
1, 2, 3, 4, 5, 6, 7
Major, Minor, Minor, Major, Major, Minor, Diminished
Hopefully, as you begin to compose stuff, you'll look at these patterns and use them to your advantage.
Chords are groups of three or more notes played simultaneously. Basically, they're like arpeggios, but the notes get played all at the same time. Chords tend to be the backbone of a lot of compositions. Only playing single notes gets really, really boring.
There are many different kinds of chords/arpeggios. We'll get to other kinds in a later tutorial.
6. Harmony Revisited
Probably the most commonly used and most pleasant harmony is created by playing a third above the note you're playing. So just like we did above, take whatever note you're on in the scale, and go two notes up. It's either a major or minor third. You can add the fifth on top of that too.
6. Chord/Key Notation
So far, we've learned three types of chords: major, minor, and diminished. If you want to write out a chord progression out on paper, or you want to write what key a song is in, there's some "notation".
The root note name by itself represents major. So if you came across:
C, F, G
You'd play C major, F major, and G major.
Minor chords are written as the root note name, but with a lower case "m" in front. Diminished chords are written as the root note name followed by "dim". It can also be followed with the "degree" symbol, but to my knowledge, ASCII doesn't have the degree symbol. ;) So here's a sample chord progression:
Am, C, Bdim, G
We'd play A minor, then C major, then B diminished, then G major.
You can also say "my composition is in the key of G" which means the key of the song is G major. Or "this song is in A minor" and it would be in the key of A minor. "But, what about the modes?!?" To be honest, I'm not too sure. I've never really heard a music teacher say "this is in the key of B dorian." For me though, I do say the name of the mode.
7. Timing
Most music we listen to is in "4/4" timing. Count out loud "ONE, two, three, four", each one equally spaced out, with an emphasis on the "ONE". The first 4 in "4/4" means that there are four notes of whatever note duration is in the second number. In this case, the second number is a 4, so that means it's a quarter note. So there are 4 quarter notes for every measure, or bar, in 4/4 timing.
In 4/4, a whole note is worth the whole measure. A half note is worth half the measure, quarter note is worth a quarter, eighth note worth an eighth, etc etc. Typically, we don't go beyond sixty-fourth note, since it's pretty impractical to write on a staff, and unless you have an extremely slow piece (like 40 beats per minute), you don't need anything faster than that. At an average speed (like 120 beats per minute), 128th notes are... superhuman, heh.
8. Simple Chord Progressions
The most common chord progression in western music is probably the "1-4-5". The numbers represent the scale degrees of the root note of each chord. In other words, if you were in C major:
C major would be 1
F major would be 4
G major would be 5
Review the scale degrees and all that other stuff if you're confused.
So if you did this over a 4 bar progression, it would be:
C major, F major, G major, C major (repeat)
Why does that sound good? It's the G major. The G is your 5th, and, for whatever reason, the human brain likes the tension it creates when you play the 5th and then the root. Simple as that.
Here a minor progression: 1, 7, 6, 7
In E minor, it looks like this:
Em, D, C, D
That's a common progression in many types of music.
Experiment, and come up with your own. Use the diminished chord sparingly.
9. Creating Melodies over Chord Progressions
Really, I can't tell you how to make up a melody. I can give you a few guidelines, though:
- Try not to make every note have the same duration. Mix it up a bit.
- Take note of the intervals that you create with the chord you're playing over top of.
- Landing on the root at the end of a long melody "resolves" everything.
- Try adding harmony to your melodies. It doesn't have to last for the duration of the melody, you can just add little splashes of harmony.
10. Summing Up
My God, I hope that made sense. If you have any questions, I'm on Pete's board.
Next time, we'll get into other chords, other scales, odd time signatures, other melody writing techniques, and the staff.
Good luck!
-The Awakened
Download a copy of this tutorial: music_pt1.txt
Coding Standards, Naming Conventions and Formatting Styles
Written by Stéphane Richard (Mystikshadows)
INTRODUCTION:
AS you've read from the title of this article, it is all about coding standards, naming conventions and
style of your source code module. The mean reason I've created this article isn't to brainwash you into
my way of doing things. This article is not the first to talk about such a subject. But what i have
elaborated here have proven themselves worth my time on all my projects both professional and personal.
There's more than one reason to do so as you'll read here and to the best of my knowledge, following these
standards and conventions, that you created yourself, might take just a bit more time in the programming
phase of your project, but it can easily save you alot of time in the debugging phase. Likewise, because
these are your standards made to follow your coding methods, it doesn't really take any of the fun out
of your programming project.
The main thing to remember in this article isn't the standard itself (although you're more than welcome
use it if you like it) but rather to give you the reasons why coding standards exist, why they can bring
benefits to your projects, even the smallest ones. It takes a little mental training to motivate yourself
to create this standard, take the extra time to name your variables, subs and other elements with clear and
relevant names. But you'll be the first to reap the rewards of implementing these practices into your own
programming endeavors. Note that I am using the standards I've elaborated in the
3rd part of my Graphical User Interfaces - A Complete Study
So the standards might look familiar as it is the standards I follow on any of my projects (big or small). I will however
elaborate on them in more details here. So then, Let's get right to it.
WHY CREATE A STANDARD AND STICK TO IT:
This is always the bigger question isn't it? Of course, if you can't find a reason to create a standard, chances
are it will be hard for you to actually create one and even more so actually follow the standard you set yourself.
What I will do here is give you the reasons why I created my own standards, and what benefits they've given me
so that you can see for yourself what standards and conventions are really all about.
- Code Readability:
Let's face it, it doesn't matter how you look at it, if you can understand what you are reading even before you
are actually reading and following code, it makes the whole learning curve much quicker. I like to keep my code
as easy to read as it is to understand the concepts within the code. When I write code, I think of two things.
The first thing is I make an effort to present the code to myself the way I would want to see any code I'd look at
and how clear I need things to be for myself. The other thing I think about is detailed in the next reason. A
project's development starts at the coding of the many modules, it doesn't end with it. The code will need to be
maintained, sometimes for months to maybe a year, in other times it could be for a decade, it really depends on
the project you are working on. No matter how long, when the code is readable, it just makes the whole process
go smooth.
- Code Maintainability:
This really has 2 distinct roles. The first is while you are working on your current project. When a standard is
follows, it allows you to almost instinctively know where things are and what possible problems have occured. In
other words, understanding the standard used quickly helps you to understand the code. Hence, when you think of a
change you need to make a change to your project, you can know where that change goes. Likewise, if you think of
a new feature you want added to your project, you can instantly know where it will go. If you document your code
clearly enough you can even know the impact that change will have. The second maintainability reason is of course
when you think of a change or addition that you want to make to a project you finished a couple years ago. Or if you
want to take an old project and port it to a new language. Knowing your standards and conventions will really quicken
the process of porting part or all of your project to that new language. As I mentionned before, the coding phase
doesn't stop when you coded your project, far from it.
- Quicker and Shorter Debugging Phase:
When you think about it, this is one of the best reasons to implement a standard. From my own experience, I've found
that when I follow a standard, one I set myself, or one set by my employers (if they are well designed of course). It
seems that I automatically change the way I code. Not just in the way I present the code, but also in the way I think
about the code before I write it down. This often results in a bit more thinking about the code I'm about to write
which means that the resulting code seems to automagically become not only clearer, but more apt to do the task. I'm
not exactly sure how that happens per se. But from what I've seen, because you have to think of the way your routines
will need to be coded to follow the standard, you are in fact manipulating the whole logical structure of your code,
not just it's presentation. As such, you are "subliminally" debugging more of your code before you put it in your text
editor. What this means is at the end of a coding process, your code is more apt to do it's designated task than it
would have been if you'd just sit down and throw the code in the editor as your brain spits it out. In my own experience
the debugging phase was reduced anywhere from 20% to even 70% depending on what I was coding. To me, even at 20%, it
represents a big chunk of time especially if your project size is bigger than usual. We could easily be talking weeks
faster all the way to months faster. Imagine that.
- Going Back To An Old Project:
Sure when you think about it, the project you're work on currently is easy to remember right? You have almost all
the routines in your head, you have a good idea where everything is in all the 1000s of lines of code that make up
that project. In your next project or in your previous project you might have worked on another game that uses 3D
or other techniques similar to the ones you are using now. In that case, it can be somewhat easier to go back to
your previous project. Think about this scenario. 2 years ago you finished making your own version of Word Perfect
and right now, you're working on an OpenGL game, you've been working at it for 2 years now, so you're pretty good with
OpenGL and 3D. That's all great. Now close your project, and reopen that Word Processing project you were working on
2 years before. Think you can locate things as quickly as you did or even understand what you were doing 2 years ago
or longer? Don't you wish you documented all those lines of code better back then? This is, by far, the most common
thing that happens with coding projects. But if you created standards, and later get back to them, it cuts off the
adaptation period quite substantially.
- Group Projects:
Whether it's a personal project that you and a couple of friends are working on or whether your business hired 20 or more
programmers to work on one single project. It's clear to see how good standards can really benefit the whole group.
Let's face it, everyone that programs has his or her own way of doing so. From the way they indent the code to the fact
that might prefer to use binary files wherever possible where another programmer might prefer random access files. If you
put 10 people on a project, and tell them all to create a routine that performs a task without talking to each other, chances
are no two routines will be the same. That's how different programmers are. All the background experience of each programmer
are responsible for the code they produce today. So, on a big group project, if all programmers can be made to follow a
standard, suddenly everyone speak closer to the same language and that makes the whole project more consistent to follow
and understand.
I don't know about you, but by reading these advantages, I'm sure just those got you thinking all of a sudden. It's clear to see
that good standards and naming conventions really helps make things more prepared for the unevitable future of programming,
changing existing code, adding new code in and remembering what you did 5 years ago. If you could find a way to give you all
these "easier things in a programmer's life", wouldn't you want to alteast give it a good try? It doesn't take a bachelor's degree
to create a standard and you don't need rocket science to be able to stick to it. All you need is the time to create it. In my case
it took about 2 good hours of thinking and writing. So it's not that much time. But the time it will save you in the long run can
be alot more than you would think possible.
So then, with all this in mind, the next logical step is to simply go right ahead and elaborate these standards. It's very important
for you to remember that these are the standards I created and like to work by. They might sound interesting to you and as such you
can definitaly used them if you want. Some of your might feel that only part of this elaboration wight be usable in your
case. Again, feel free to use this in whole or in parts. The real idea behind this whole article is to help you find a way
to organize your code in a way that will help you work on projects without being overwhelmed by the code you have done or
the code you are about to undertake. Simple organization prior to coding as well as some common sense is really all it takes. So
het's talk about these standards.
CODING STANDARDS:
The standard I'll be using is broken down into three workable standard groups. These are the
"Source File Documentation", "Indentation and Spacing" and "Naming Conventions". As I mentionned,
coding standards are there because when the code gets big, it's clarity will have better chances
at staying as clear as possible across the thousands of lines of codes there will be. Let's take
the time to review these standards right here.
- Source File Documentation:
When creating a source file, often, documentation of this source file is quickly neglected
usually because of lack of time, some think time is better spent actually coding the intended
purpose and say to themselves: "I'll document it when it works!". I myself often used that
technique as well because when there's no time there's no point. However, this project has
no deadlines. Like everyone else, I want my things done yesterday but this is suicidal on
any project that you deem a big project. I'd rather wait (as impatient as I am), as long as it takes, to be sure
that what I get is both readable and understandable. As such I try to give a special effort to
comply with the following standards.
- Module Level comments:
This is usually done at the beginning of a module, it should have the module name, project
to which it belongs, version number, creation date, author name, and other standard information
of this nature. It should also have a paragraph that explains it's purpose clearly. It could be
a sentence, sometimes a sentence is enough, other times more information is needed. Common sense
will play a role to determine how much information is needed. Right after this I leave a comment
section to add "things to do" so I don't lose track of thing or forget something that should have
been done. Finally, at the end of the module, I also like to have a history section, at the end of
the source module, so that I can track the work done. Here is a sample Module header comment, taken
from my ErgonOS GUI project:
' ===================================================================================
' NAME: Ergon O.S. (Ergonomic Operating System)
' FILE NAME: ErgonOS.bas
' FILE TYPE: Main Program Module
' VERSION: 1.00.000a Build 0001
' DATE CREATED: Wednesday, October 26th, 2005
' -----------------------------------------------------------------------------------
' DESCRIPTION: This module calls upon the functionality of other modules in order
' to validate the command line parameters and act upon them. Then it
' will load the configuration file, initialize all sub systems and
' present the Ergon O.S. GUI to the user.
' ===================================================================================
' PROJECT NAME: Ergon O.S.
' PROJECT TYPE: Graphical User Interface
' VERSION: 1.00.000a Build 0001
' PROJECT URL: Coming Soon
' LANGUAGE: FreeBasic Version 0.15b and higher
' TARGET: DOS 32 Bits
' -----------------------------------------------------------------------------------
' DESCRIPTION: Ergon O.S. is a Graphical User Interface Project designed to be a
' document based User Interface. To best describe this project, you
' simply need to think of the GUI as a document based interface
' rather than an application based interface as commonly seen these
' days.
' ===================================================================================
' AUTHOR NAME: Stephane Richard
' NICKNAME: MystikShadows
' EMAIL: srichard@adaworld.com
' WEBSITE: Coming Soon
' -----------------------------------------------------------------------------------
' COPYRIGHT: Copyright (c) January 2005 - Stephane Richard
' LICENSE: Licenced under G.P.L. Version 2 for OpenSource Projects
' Licenced under B.S.D. for freeware/shareware projects
' DISTRIBUTION: Allowed in concordance to the G.P.L. Version 2
' ALTERATIONS: Allowed as under the terms of the G.P.L. Version 2
' ===================================================================================
- Procedure Level comments:
This is usually done at the beginning of a procedure or function. It should have
the name of the function or procedure, a list of parameters and their types and an indication on
whether a parameter is optional or defaulted to a value somehow. It should state what the function
returns, if any, what it assumes, what valid values are acceptable for parameters in the case of
dates for example, perhaps a date can't be earlier than a certain date. And a paragraph on the role
of the procedure or function. Once again, here's an example to illustrate this:
' ===============================================================
' NAME: LoadConfiguration()
' PARAMETERS: ConfigFile AS STRING
' RETURNS: 0 if no errors, Err number if anything happened
' ASSUMES: ConfigFile is valid path and file name.
' CALLED FROM: ErgonOS.bas Main Program Section
' ---------------------------------------------------------------
' DESCRIPTION: This Sub takes the passed configuration file
' name, opens it and loads up the values into the
' appropriate User Defined Types so that they are
' available to the rest of the application.
' ===============================================================
FUNCTION LoadConfiguration(ConfigFile AS STRING) AS INTEGER
...
END FUNCTION
- Source Level comments:
This is done just before a certain block of code within a procedure or function. usually one or two
sentences to explain the code to come when the developer knows it's a tricky part to understand. Again,
logic and common sense should guide this level of documentation, some code are clear enough as is, some
require some explanation. Before you decide that no comments are needed, think about the long term for a
bit and picture youself going back to this non commented code in a couple of years. If you're very active
in a very different type of programming project, you might not even need a couple years but only a couple of
months to see how looking at the same code can get confusing. Every bit of clarity helps in this case.
And that's it, as far as commenting the code goes. Again these are suggestion, if you feel more than this should be
done, go right ahead and do it. But I believe that with this strict minimum of documentation that it will help everyone
involved, including yourself.
- Indentation and Spacing:
Indentation, to me, helps to clearly determine where a block of code begins and where it ends. For the number
of spaces to use, that's irrelevent, whatever the preference may be just as long as it's clear enough to visually
see the beginning and end of a language contruct. I believe at least 2 characters should be used, but aside that,
any indentation style is left up to the developer. Me I usually align to the next Item. like so:
IF ThisVariable = 1 THEN
CALL ThisSub
END IF
FOR Counter = 1 TO 10
CALL ThatSub
NEXT Counter
The main reason for this is that to me Aligning the CALL ThisSub under ThisVariable and ThatSub under Counter like I
did is visually cleaner in my opinion. That's just my opinion however and if I was to receive code that wasn't aligned
this way I wouldn't refuse it. Everyone has their own style of coding. Me I just happen to like it that way.
Usually indentation is used for Class definitions, If Then Else constructs, Loops, Procedure and Function declaration
and the rest of the code is then indented to the level where it should be to visually show that it is part of a given
construct. Many editors even have an Auto-Indent feature that can do a good job at indenting code for your in a more
than acceptable means. In other cases, most language have a "code beautifier" or code formatter program that can take
a source file and spruce it up visually speaking.
Common sense is really what it's all about here. If the code looks clear enough to understand then it should be perfect
just the way it is. It's all visual aids that help other understand the source file, so it should be used as a documentation
tool.
- Naming Conventions:
As far as naming conventions goes, well common sense and logic will play a very big role here as well.
When naming a source file, a procedure or function, a class definition or a variable, one has to think of others
that haven't seen the code yet. What can they say about the names you've chosen determines the quality of the
naming convention used.
- File Names:
When naming a source file, a form, a database, whatever the case may be, it's important to
keep the name of the file as clear as possible as far as it's intended purpose is concerned.
Basically, I name my module based on what they pertain to. For example, if a module has user
defined types and is at a global (read shared) module I would typically call it "SharedUserTypes.bi".
However, if the module has specific string parsing module for a scripting engines I would more
than likely call it "ScriptParserFunctions.bi". Now that the OS doesn't limit us to 8 characters and 3
for the file extension, we can more freely use wise naming conventions like these making the whole
project that much clearer.
- Class Names:
Well a class is an object and therefore should be named according to how you would name any other
objects. If you are defining a class for animals for example, simply call it AnimalClass, it needs to speak
for itself. Common sense should once again help here. When other people look at your code, they will know, by
reading "AnimalClass" that what you are refering to is a class definition that defines an animal data type. Since
all classes are created to define an object, they can all follow this type of naming convention regardless of the
class type. Attention to these little details help clear things up a lot. Imagine if you called it just Animal.
What would tell them that this is a class definition? They would have to go to it's definition to see what it is and
that is just a waste of time. In my case, Classes are named <ClassName>Class, User defined types are <TypeName>Type this helps
clearly define what the data type is. One of the very wide spread naming convention is called The Hungarian Notation and
has existed for quite some time already. It has advantages but to me, in many ways, the means by which it gives details to a
variable name also makes the code a bit more cryptic in my opinion, but go ahead and read about it, you might like it
enough to use it all the time, which is why I provided the URL to it. It's very wide spread and if you plan on
working as a programmer for a living, you should probably get familiar with it if you haven't done so already.
- Procedure/Function Names:
A procedure or a function usually perform an action or a calculation, therefore, it is recommended that
the procedure or function name start with a verb stating that action followed by a name of what that action
is perform on. For example a function that would caculate the tax on a given amount should be called CalcTax or CalculateTax.
By always making sure the verb used clearly identifies the action taken, there will never be a surprise as to
what the function should be doing. The parameters of the procedure should follow your variable naming convention
again to keep your code as compliant to your standards as possible.
- Variable and DataType Names:
A variable stores information to be used later or elsewhere in the module or a given project (depending on their scope). A name, aside standard variable naming conventions (start with a letter, followed by numbers or other letters etc etc..) should
tell, by its name, what information it will store at the very least for the sake of clarity of code. A DataType
(User Defined Type that is) is a structure that will more than one piece of information It's name will need to represent the data it will hold clearly as well as end with Type to clearly see it's a TYPE definition. For example, CoordinateType. A variable
declared as that type will omit the Type ending. Hence <scope> Coordinate AS CoordinateType. Depending on the situation, an array of a given TYPE definition will be TypeNameList or the plural form of the TypeName. Finally, Global variables declaration
will start with Global and the name of the variable. Again, you could use the Hungarian Notation system if you'd like, the choice is up to you. Note that I like to align my type definitions (as you'll see here), to me, it helps make then easier to read and to identify when scrolling quickly through the code.
Here's an example of all these:
' --------------------------------------------------------
' NAME: WindowType
' DESCRIPTION: This User Defined Type holds the needed
' information to display and manage a
' window on the screen.
' --------------------------------------------------------
TYPE WindowType
WindowNumber AS INTEGER
WindowTitle AS STRING
WindowTop AS INTEGER
WindowLeft AS INTEGER
WindowHeight AS INTEGER
WindowWidth AS INTEGER
ForeColor AS INTEGER
BackColor AS INTEGER
END TYPE
DIM Window AS WindowType
DIM WindowList() AS WindowType ' OR
DIM Windows() AS WindowType
DIM SHARED GlobalWindows() AS WindowType
Once again, with these coding standards in place, I think that the whole development effort will only be made easier
by trying to follow these as much as possible. There is no deadlines here, taking the time to comment and name things properly
will bring the quality of the project that much higher, in my belief. When you think of the thousands of lines we'll be dealing
with, having a standard coding style and naming convention like this really help you to know exactly where things belong as well as
and why they were named the way they were named. Now these are my standards, you could definitaly create your own that fits your
way of coding (I really can't stress this enough, it's all about how you like to work when you code and what you know you can really
stick to easily and painlessly).
ERROR MANAGEMENT:
In big projects, if you don't implement error management right from the start, it will be a major
headache to add it later in the project or at the end after you're done coding everything else. For this reason alone
I talk about error management as part of a convention because like the rest of your standards and conventions, they need
to be implemented from the start so they don't quickly become quite an overwhelming task. However, doing it from the start
like this, you can integrated it easily to your coding routine and almost not have to worry about it. At the end
you'll end up with all your error management done and be ready to move on to the next step of your project right away.
Throughout all the modules, each sub and function, when implementing the error management code,
you might want to think about the reasons why you are implementing error management. As far as I'm concerned
One of the main reason I implement error management is because of the debugging phase and the other
errors that might occur afterwards as users actually use my program. As such, I need a system that
can point me as close as possible to the erroneous code. This way I don't have to spend too much time
locating where the error is actually happening. For that to successfully occur, I
need a certain list of information to help me in my quest. Whether the bug is reported on screen or
logged to a file this information will still help locating bugs quickly. Here's that information: (note that
this is also in my 3rd part of my GUI series).
Error Information
|
Description
|
Engine Name
Module Name
Sub/Function Name
Parameter List
Error Number
Error Description
|
The Engine name is displayed
The Name of the .bas or .bi file
The Sub or Function Name
The values of the parameters passed
The error number as returned by ERR
A human readable description of what the error means
|
This essentially means that whenever an error is returned by the system, it will give me back these specific pieces of information. By knowing
right from the start, the Engine where the error occured, the module name, the sub or function name, the values of the
parameters that were passed to that sub or function (if any) and the error that occured, imagine how fast the debugging
process will suddenly become for me, or anyone else correcting the error. Here is an example of a typical function and how I will provide the
needed information. Let's assume that this function will be in a module called MouseControl.bas and that the project is called
DrawingPad:
' =============================================
' NAME: MouseOverControl()
' PARAMETERS: XPos AS INTEGER
' YPos AS INTEGER
' Width AS INTEGER
' Height AS INTEGER
' MouseX AS INTEGER
' MouseY AS INTEGER
' ASSUMES: Parameters are positive values
' RETURNS: True if mouse is on top of the
' control, False if it is not.
' CALLED FROM: EVRIL's main logic loop.
' ---------------------------------------------
' DESCRIPTION: This function will take the
' position and dimensions of a
' control, do the math to get
' the range of coordinates that
' the mouse need to be in to be
' considered to be on top of the
' control and compare the mouse
' coordinates to see if it falls
' within the control's range. If
' it does, True will be returned
' to the calling sub. If it's
' not on top of it, False will
' be returned instead.
' =============================================
FUNCTION MouseOverControl(XPos AS INTEGER, YPos AS INTEGER, _
Height AS INTEGER, Width AS INTEGER, _
MouseX AS INTEGER, MouseY AS INTEGER) AS INTEGER
' ------------------------------------------------
' We create a variable to hold the error message
' ------------------------------------------------
DIM ErrorMessage AS STRING
DIM BottomRightX AS INTEGER
DIM BottomRightY AS INTEGER
DIM WorkResult AS INTEGER
' --------------------------
' Turn in Error management
' --------------------------
ON LOCAL ERROR GOTO ErrorManager
' ---------------------------------------
' Evaluate the bottom right coordinates
' ---------------------------------------
BottomRightX = XPos + Width - 1
BottomRightX = YPos + Height - 1
' ------------------------------------------------------------
' Compare Mouse coordinates to control's area and return the
' proper value of the function based on if the mouse is over
' the control or not.
' ------------------------------------------------------------
IF (MouseX >= XPos AND MouseX <= BottomRightX) AND
(MouseY >= YPos AND MouseY <= BottomRightY) THEN
WorkResult = True
ELSE
WorkResult = False
END IF
' -------------------------------------------------------------
' Return the value and exit the function right here before
' execution of the error management section can take place
' if no error occured.
' -------------------------------------------------------------
MouseOverControl = WorkResult
EXIT FUNCTION
' -------------------------------------------------------------------
' This is where the error management message is created and printed
' -------------------------------------------------------------------
ErrorManager:
' -------------------------------------------------------
' First step is to formulate the complete error message
' -------------------------------------------------------
ErrorMessage = "Engine: DrawingPad" + CHR$(13) + _
"Module: MouseControl.bas" + CHR$(13) + _
"Function: MouseOverControl" + CHR$(13) + _
"Parameters: (" + STR$(XPos) + ", " + _
STR$(YPos) + ", " + _
STR$(Height) + ", " + _
STR$(Width) + ")" + CHR$(13) + _
"Error: " + STR$(Err) + ":" + Err$
' -------------------------------------------------------------
' Next we either display the error or append it to a log file
' -------------------------------------------------------------
IF ErrorLogging = True THEN
LogError(ErrorMessage)
ELSE
DisplayError(ErrorMessage)
END IF
' ---------------------------------------------------------------
' In this case, we resume execution loging or showing the error
' ---------------------------------------------------------------
RESUME NEXT
END FUNCTION
IN CONCLUSION:
And there you have it, the coding standard documents comes to an end. If you've paid attention, you can see that
the major factor you need to remember when creating your coding standards is that they have to make sense to you now
and in a year or 2 if you need to get back to that same code. If just that stays in your mind after reading this, I
will be able to say mission accomplished. Too many times I've seen people code away for months, leave to work on another
project and be baffled when they need to get back to that project. Too many times I've joined projects that didn't follow
any standard imaginable. It's really amazing what a couple of hours (maybe a days work) defining a standard can do to
the overall coding process. How much it can help during and after the programming phase. This is the major reason why
I wrote this article. Is to make you think about it.
What's to say next? Are you going to create your standards or keep working the way you are now? That decision is up to you
some might have the natural gift to code so clear that not understanding what's happening is simply not an option. Others could
benefit from such a standard being in place. But that's just as far as code readability goes. For maintainability purposes
however, I strongly believe that having a standard in place can only have benefits. Sure when deadlines are concerned people tend
to think that standards just waste too much time, but that's usually because they didn't know what I've shared with you right here.
When it comes to deadlines, there's one thing you need to think about. Do you want to spend a day creating a better standard or delay
your release 3 or 4 weeks because you are lost in 1000s of lines code somewhere thinking (maybe I should have created a standard)? That
answer is simple to me, isn't it to you? Until I write again, feel free to email me with comments or questions. Happy coding.
MystikShadows
Stéphane Richard
srichard@adaworld.com
Download this tutorial: codingstandard.html
How To Build a Shell For Qbinux, Part 1
Written by Seb McClouth
Shell, what's that?
You might know the SHELL-command in Qbasic/QB. And if you run it just
as SHELL, you'll get a commandprompt. And that's the shell. If you
don't have a shell... your OS simple won't work. The Shell
communicates your commands to the kernel which will run it.
In Qbinux, just like in Linux, Shell is the first program to be loaded
when you log in, and keeps on running until you log out.
You have downloaded Qbinux and you think... Qbash is not really the
thing I want... I want to create more sumfin of my own...
It's possible...
What do you need?
The Qbinux core ofcourse... And some experience in programming.
In order to get more comfortable with this, we first gonna build a
basic shell... which is not capable of doing anything yet but it's a
start. Along the way you can add things you'd like to see in your own
shell.
And remember, if you have any questions... don't hesitate to e-mail me.
Create a new file call sh.qs0 or whatever-name-you-like.qs0 and place
it into the map shell. Then edit the compile.bat file and change the
qbash to your shell.
For a non-working-basic-shell you need the following code:
ff = FREEFILE
IF CVL(CurDrive) = 0 THEN cp$ = "root:"
DIM dm(2048) AS STRING
DO
IF CurDir <> ocdir$ THEN
ocdir$ = CurDir
cp$ = ""
t$ = CurDir
IF t$ <> MKL$(0) THEN
DO
t$ = GetName(LEFT$(t$, 4), 1)
cp$ = cp$ + RIGHT$(t$, LEN(t$) - 4), 1)
LOOP UNTIL LEFT$(t$, 4) = MKL$(0)
cl = 0
FOR a = 1 TO LEN(cp$)
t$ = MID$(cp$, a, 1)
IF t$ <> "/" THEN
g$ = g$ + t$
ELSE
dm(cl) = g$
cl = cl + 1
g$ = ""
END IF
NEXT
cp$ = ""
FOR a = cl -1 TO 0 STEP 01
cp$ = cp$ + dm(a) + "/"
NEXT
ELSE
IF CurDir <> MKL$(0) THEN
t$ = GetName(CurDir, 1)
cp$ = RIGHT$(t$, LEN(t$) - 4) + "/"
ELSE
cp$ = ""
END IF
END IF
END IF
IF pcom = "" THEN
PRINT cp$;"#";
LINE INPUT "", com$
ELSE
com$=pcom$
END IF
That's it for now. Till next time.
Seb McClouth
http://mcclouth.tk or http://www.freewebs.com/qbinux
balai_goyan@yahoo.com
Download this tutorial: qbinux_shell_pt1.txt
A Course in FreeBasic: Chapter 2
Written by Rattrapmax6
Introduction:
Well, it's been some time since chapter one. And now we will continue on where I left off last time with Variables and Constants. In chapter one you got a little taste of these so you could see how the INPUT function worked. In this chapter, I will explain in pretty good detail the some of the many ways to use Variables and Constants, and a few of the codes that alter or render them.
Variables VS. Constants: In greater detail..
Variables are values in your program that will change over the course of its operation. Much like I said last time, things such as age, time, the position of something (That moves), or any number of things. Variables exsist in just about every program you run, and thus are a great way to control events in a game, or trigger errors when something goes wrong in your application, or game.
Constants are values in your program that do not change over the course of its operation. Things such as mathimatical constants (e.g., pi, g, etc.), a person's name, a creature's type (e.g. Horse, dog, cat, etc.) or many other things. Constants are very helpful when it comes to programs that use a lot of math constants so you only have to type the names insted of their long values.
Strings:
Strings are variables/constants that store text values, and numbers stored as strings are considered text. Stings are noted to the compiler by a $ symbol at the end of their name, unless they are DIMed as an string. Here is an example of the two types:
'A normal string..
stringname$ = "Text value.."
'A DIMed string (Show as DIM AS STRING, but can be DIM stringname AS STRING like in QBasic)..
DIM AS STRING stringname
stringname = "Text value.."
Strings have severial functions that can use or alter them. Two of them you already know as PRINT and INPUT. PRINT will read the value from the string and display it to the screen, where as INPUT stores a user defined value to the string. There are several commands that involve strings, but those will be covered in their correct time.
Numbers:
Numbers are variable/constants that may be of severial types. These are bytes, shorts, integers, longs, singles, and doubles. Each have their own perpose for storing numbers, and some can be either signed or un-signed. Here is a list of the data types:
BYTE: Is a 8-bit signed whole-number that can hold a
value between: -128 to 127.
UBYTE: Is a 8-bit unsigned whole-number that can hold
a value between: 0 to 255.
SHORT: Is a 16-bit signed whole-number that can hold
a value between: -32,768 to 32,767.
USHORT: Is a 16-bit unsigned whole-number that can
hold a value between: 0 to 65,365.
INTEGER: Is a 32-bit signed whole-number that can hold
a value between: -2,147,483,648 to 2,147,483,647.
UINTEGER: Is a 32-bit unsigned whole-number that can
hold a value between: 0 to 4,294,967,295
LONG: (Same as Integer)
LONGINT: Is a 64-bit signed whole-number that can hold
a value between: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
ULONGINT: Is a 64-bit unsigned whole-number that can hold
a value between: 0 to 18,446,744,073,709,551,615
SINGLE: Is a 32-bit floating point number that can hold
a value between: 1.1 E-38 to 3.43 E+38.
Its precision is of 6 decimal digits.
DOUBLE: Is a 64 bit floating point number that can hold
a value between: -2.2E-308 to +1.7E+308.
Its precision is of 14 decimal digits.
Data types are assigned to a variable/constant by the use of DIM. A quick note on how DIM can be used before we continue: DIM can assign the same type to multible values by using DIM AS (Type), or it can assign values to each one to be DIMed. You also have CONST which sets a constant to be caried over the whole program. Examples:
DIM
'DIM all varibles AS BYTEs..
DIM AS BYTE variable1, variable2, variable3
'DIM each varible AS diferent types..
DIM variable1 AS BYTE, variable2 AS INTEGER
CONST
'Constants
CONST PI = 3.14
CONST LENS = 256
Now that you see the basics on how DIM works, I will continue with an example code on using a few of the types so you can get an idea of their uses.. :
'DIM an Integer and a Single...
DIM numint AS INTEGER, numsng AS SINGLE
'Give both a value of 100.5...
numint = 100.5
numsng = 100.5
'Print both values and see what you get...
PRINT numint; " <-- Integer."
PRINT numsng; " <-- Single."
SLEEP
Basic ways to use Variables/Constants:
So, now that you know the different data types, you probaly want to have something to do with them. Here are some fun little sample programs that you can study and see a few ways to use these different types:
Variables
'Make a String and three Shorts
DIM AS STRING username
DIM AS SHORT syear, eyear, age
'Get user's name...
INPUT "Hello, who are you"; username
'Make a space so lines don't run together...
PRINT
'Welcome user...
PRINT "Hi, "; username; "."
PRINT
'Ask user for his/her birth year...
INPUT "What year were you born? (####): ", syear
PRINT
'Ask user for the current year...
INPUT "What is the current year? (####): ", eyear
'Calculate user's age..
age = eyear - syear
PRINT
'Tell the user how old the user will be on his birthday...
PRINT "On your birthday in"; eyear; ", you will be"; age; "."
PRINT
'Tell the user good bye...
PRINT "Have a nice day, "; username; "."
'Pause long enough for user to see the last message...
SLEEP
Constants
'DIM are variables...
DIM AS SINGLE ANG ,RAD
CONST PI = 3.14 'Set the constant..
ANG = 40 'Our angle to make a Radian..
RAD = ANG * PI / 180 'Make the angle a Radian..
PRINT "Original Angle:"; ANG
PRINT
PRINT "The Radian value:"; RAD
SLEEP
The comments explain what the code does, and you should by now be able to understand the commands I used. Well, that wraps up this tutorial on using variables, so until next time, happy coding, and have fun!
PS: No debugging tips since the tips from the last chapter will work here if problems arise.
Contacting me:
EMail: Rattrapmax6 on AOL
Webpage: My Site...
Download a copy of this tutorial: fbc2.html
Programming the Multiprocessing Core for QB 4.5
Written by Nick Verlinden
Prologue
Why in gods name do you want a multitasking core for qb someone once asked, I could use it for
allot of things. For monitoring multiple subs at once. You never wanted to to display the time in a custom
sized text box while playing a game? This is the reason I programmed this thing. The only criple
thing in QB 4.5 was the lack of running mutiple subs at once (not to mention the speed, but hey..).
I'm trying to make a librarie out of it, but first i'm going to introduce to you the first beta release.
I kept the alpha releases silent because I didn't want to be overkilled by questions etc, and the alpha
versions contained allot of bugs. May it be usefull or not, here it is anyway.
The reason I'm writing this article/tutorial is because it isn't that simple to program subs in QB 4.5
without knowing how to trap loops. This is a big adaptation. But I must say I'm stunned when
I saw how it actually affected the running speed. It's faster than I thought it would be.
A sub with a dry loop (meaning only doing variable math) can go as fast as 666 loops per second
on a dos box in windows. So it might even come in handy. In this tutorial I hope to learn you
how to do multiprocessing loops, a better understanding of the program. I will keep messing around
with my core until it ultimatly becomes complete. But what is complete? That's why, if you have any
suggestions and/or questions, you may contact me on my e-mail address listed at the end of this document.
I'm going to explain the basics first, and then we go further into detail like all the variables.
Right, let's get busy.
Chapter 1
The Core
It's probably not as spectacular as it sounds, but hey, I put my efforts in it and I'm proud of it.
How does the core work you ask? Simple, I keep track of all kinds of stuf in variables.
An example would be nice right? ok, here it is:
I want to add a task, let's display the clock. (In my demo, there is a sub called display.time)
so what the shell (in my demo, it's the sub CMD) does is, it opens a new array with the process
ID as holder, it sets all kind of variables. The most important varible is this: run.appshelf(ID%).
The system goes into it's usual loop 'systemidle' and it checks all the registered arrays if there
is a program to run, if the variable in array run.appshelf(ID%) = 1 then the system will execute
the given script with a simple sub I made called script.appshelf(ID%). So basically, the source
can be converted to any language possible. Now that you have a better understanding of how
the core works, lets look at my built in shel CMD. One important thing is due to the limitations
of QB 4.5 I only made a 255 array, meaning that there can be a maxx of 255 processes because
the system is process 0.
CMD
CMD, a biult in sub I made for directing the system core. This is just a simple example and is
probable not the most efficient way to use it. Lets look at the source. It reads in a command from
the command line, and then adds the process to the systemcore by setting the variables in the
sub add.process.
SUB CMD (ID%)
loopy.appshelf(ID%) = 0
screen.erase 1, 1, 1, 70
Sinput Inp$, "-->", 1, 1, 60, 7, 0, 0
IF LEFT$(UCASE$(Inp$), 4) = "KILL" THEN kill.appshelf(VAL(RIGHT$(Inp$, 1))) = 1: VAL(RIGHT$(Inp$, 1))
IF LEFT$(UCASE$(Inp$), 3) = "ADD" THEN a% = add.process("", RIGHT$(Inp$, 1), "USERPROC", 1)
IF LEFT$(UCASE$(Inp$), 3) = "VAR" THEN display.variables VAL(RIGHT$(Inp$, 1))
IF LEFT$(UCASE$(Inp$), 5) = "FLOOD" THEN flood.kernel VAL(RIGHT$(Inp$, 3)), "1"
IF LEFT$(UCASE$(Inp$), 7) = "TASKMON" THEN a% = add.process("", "6", "Display Process call", 1)
IF LEFT$(UCASE$(Inp$), 3) = "PRC" THEN display.process 10, 1 'ELSE LOCATE 3, 1: PRINT "Unknown command"
IF LEFT$(UCASE$(Inp$), 3) = "END" THEN END
IF LEFT$(UCASE$(Inp$), 4) = "CALC" THEN a% = add.process("", "8", "Calc test", 1)
IF LEFT$(UCASE$(Inp$), 7) = "CHRONOS" THEN a% = add.process("", "7", "Chronos monitor", 1)
IF LEFT$(UCASE$(Inp$), 6) = "DOLOOP" THEN a% = add.process("", "9", "Do Loop test", 1)
IF LEFT$(UCASE$(Inp$), 4) = "LAST" THEN storeloc 0: LOCATE 23, 1: PRINT "LastID%: " + STR$(LastID%): restoreloc 0
IF LEFT$(UCASE$(Inp$), 3) = "CLS" THEN CLS
IF LEFT$(UCASE$(Inp$), 7) = "DOMULTI" THEN a% = add.process("", "10", "Multiloop test", 1)
run.appshelf(ID%) = 1
END SUB
As you might have noticed this is a command line, and it uses the sub Sinput instead of the
usual INPUT function in QB 4.5. This is because the processes should still keep running even
if you are typing in a command. The sub is not mine, I did not program it, I just modified it a little
to work with my core. It's a good piece of code, too bad I don't have the name from who might
have written it. Sorry fellow programmer, if you might read this article. The input is checked for
a known command. lets look at the first line, it says KILL, if you couldn't figure out what it did,
it kills processes running in the systemcore. then a 1 character variable (because I was too lazy
to make a line that can read arguments) and takes it as the ID. I want to know the ID of a running
process? ok, type in PRC or TASKMON, the prc command does only display the current running
processes, taskmon updates constantly until killed. The add command is just written for my
own debugging purposes. CALC does a random calculating job in 2300 loops. CHRONOS is the
main trigger for refreshing applications sush as TASKMON, every second that passes it updates the
status of the programmes on the screen. DOLOOP is a never ending loop, wich is just a process that
i used for seeing if the system slows down. LAST prints the last ID that is used by the processes.
What you might want to know is, that if a process is finished it's ID is recycled, so if there are
5 processes running, and you end the fourth process, then you add another, it uses the fourth ID.
CLS clears the screen. DOMULTI does a multiloop sub, so a sub with more than one loop in it.
It will finish after the two loops reach 1000. CMD itself is also a process. But if you kill it, there's no
way to end the program, so be warned.
FUNCTION Add.process(ID%)
This sub sets the basic variables that the systemcore needs to know. What type of app is it,
is it initialized (this variable is for the ID recycling), does it need to be activated, what is the name,
the linescript, what kind of user is it, what file to execute...
I made this a function so it can return an error if something wasn't right, but that's not implented yet.
FUNCTION add.process% (file$, script$, name$, user%)
'PRINT "Add a process trigger": SLEEP 'debugging
ID% = FreeID%
type.appshelf(ID%) = 0
init.appshelf(ID%) = 1
run.appshelf(ID%) = 1
name.appshelf(ID%) = name$
linescript.appshelf(ID%) = script$
user.appshelf(ID%) = user%
file.appshelf(ID%) = file$
loopy.appshelf(ID%) = 0
END FUNCTION
SUB script.appself(ID%)
The script sub just executes what is needed, for example if the linescript is "10"
it runs the multiprocess sub. Lets look at the source.
SUB script.appshelf (ID%)
IF file.appshelf(ID%) = "" THEN GOTO linescriptz ELSE GOTO runfile
linescriptz:
IF linescript.appshelf(ID%) = "1" THEN disp.time ID%, 1, 70
IF linescript.appshelf(ID%) = "2" THEN disp.time ID%, 1, 60
IF linescript.appshelf(ID%) = "3" THEN CMD ID%
IF linescript.appshelf(ID%) = "4" THEN disp.time ID%, 1, 50
IF linescript.appshelf(ID%) = "5" THEN calc.flood ID%
IF linescript.appshelf(ID%) = "6" THEN display.processu ID%, 10, 1
IF linescript.appshelf(ID%) = "7" THEN display.chronos ID%
IF linescript.appshelf(ID%) = "8" THEN calc.flood ID%
IF linescript.appshelf(ID%) = "9" THEN do.looptest ID%
IF linescript.appshelf(ID%) = "10" THEN do.multiloop ID%
GOTO endsubscr
runfile:
filehandle.appshelf(ID%) = FREEFILE
OPEN file.appshelf(ID%) FOR BINARY AS filehandle.appshelf(ID%)
IF LOF(filehandle.appshelf(ID%)) = 0 THEN CLOSE filehandle.appshelf(ID%): KILL file.appshelf(ID%)
GET filehandle.appshelf(ID%), , tempvar
IF tempvar = 1 THEN disp.time ID%, 1, 1
CLOSE filehandle.appshelf(ID%)
GOTO endsubscr
endsubscr:
END SUB
What happens within here? It checks the process Script.appshelf(ID%) variable, it's a string.
First we check the file.appshelf(ID%) variable wich holds the filename of a script to execute.
If this varible is empty check the linescript.appshelf(ID%) variable. lets look at script 10. It's
the DOMULTI sub!, so if the variable is "10" then he activates the do.multiloop sub.
What have we learned?
If you want to use my built in CMD, then you must first write a line of code in the sub wich tells
the system what to do when that command is typed. Then type a line of code in the linescript sub
what sub to launch. Later on I will try to teach how to program a shell for the core.
We are almost writing our first MultiProC program. Read further about
it in the next chapter.
Chapter 2
Program Design
Now that you have an idea of how the core works internally, let's build our own little application.
What kind of application? Something simple off coarse for starters.
We are going to make a date displaying SUB
What you need to know:
The program type we are making is a program that doesn't loop on it's own, meaning that the
system keeps running the program as long as it isn't killed.
I'm going to explain line per line to make it more clear.
SUB display.date (ID%,X%,Y%)
We take the x and y arguments to display the date on a specific location. And if you are
programming a sub that wil not run within the core, then we must always give the process
ID wich is given bij add.process.
loopy.appshelf(ID%) = 0
This line sets the systemvariable loopy to 0, so that the system knows it must be run every cycle,
if you set it to 1 then the system will ignore that process because it loops on it's own. Else you get
an error message out of stack space, because the sub keeps running deeper and deeper, it's a
neverending loop opening the sub. In this case, this isn't actually needed, because the add.process
sub already sets the value to 0.
LOCATE X%,Y%:PRINT DATE$
We set the cursor location to X% and Y%, and print the date on this location.
END
End of the sub.
So maybe to see the sub in total:
SUB display.date (ID%,X%,Y%)
loopy.appshelf(ID%) = 0
LOCATE X%,Y%:PRINT DATE$
END
Okay, we designed the sub. Now to add it in the command shell:
SUB CMD (ID%)
loopy.appshelf(ID%) = 0
screen.erase 1, 1, 1, 70
Sinput Inp$, "-->", 1, 1, 60, 7, 0, 0
IF LEFT$(UCASE$(Inp$), 4) = "KILL" THEN kill.appshelf(VAL(RIGHT$(Inp$, 1))) = 1: VAL(RIGHT$(Inp$, 1))
IF LEFT$(UCASE$(Inp$), 3) = "ADD" THEN a% = add.process("", RIGHT$(Inp$, 1), "USERPROC", 1)
IF LEFT$(UCASE$(Inp$), 3) = "VAR" THEN display.variables VAL(RIGHT$(Inp$, 1))
IF LEFT$(UCASE$(Inp$), 5) = "FLOOD" THEN flood.kernel VAL(RIGHT$(Inp$, 3)), "1"
IF LEFT$(UCASE$(Inp$), 7) = "TASKMON" THEN a% = add.process("", "6", "Display Process call", 1)
IF LEFT$(UCASE$(Inp$), 3) = "PRC" THEN display.process 10, 1 'ELSE LOCATE 3, 1: PRINT "Unknown command"
IF LEFT$(UCASE$(Inp$), 3) = "END" THEN END
IF LEFT$(UCASE$(Inp$), 4) = "CALC" THEN a% = add.process("", "8", "Calc test", 1)
IF LEFT$(UCASE$(Inp$), 7) = "CHRONOS" THEN a% = add.process("", "7", "Chronos monitor", 1)
IF LEFT$(UCASE$(Inp$), 6) = "DOLOOP" THEN a% = add.process("", "9", "Do Loop test", 1)
IF LEFT$(UCASE$(Inp$), 4) = "LAST" THEN storeloc 0: LOCATE 23, 1: PRINT "LastID%: " + STR$(LastID%): restoreloc 0
IF LEFT$(UCASE$(Inp$), 3) = "CLS" THEN CLS
IF LEFT$(UCASE$(Inp$), 7) = "DOMULTI" THEN a% = add.process("", "10", "Multiloop test", 1)
IF LEFT$(UCASE$(Inp$), 4) = "DATE" THEN a% = add.process("", "11", "System Date", 1)
run.appshelf(ID%) = 1
END SUB
The line in bold is the line we added, now command knows if date is typed, he must add a process
with the script "11". But as you know the next thing systemidle will be looking for is script.appshelf
we also have to add what this script "11" actually does, so we will add it like this:
SUB script.appshelf (ID%)
IF file.appshelf(ID%) = "" THEN GOTO linescriptz ELSE GOTO runfile
linescriptz:
IF linescript.appshelf(ID%) = "1" THEN disp.time ID%, 1, 70
IF linescript.appshelf(ID%) = "2" THEN disp.time ID%, 1, 60
IF linescript.appshelf(ID%) = "3" THEN CMD ID%
IF linescript.appshelf(ID%) = "4" THEN disp.time ID%, 1, 50
IF linescript.appshelf(ID%) = "5" THEN calc.flood ID%
IF linescript.appshelf(ID%) = "6" THEN display.processu ID%, 10, 1
IF linescript.appshelf(ID%) = "7" THEN display.chronos ID%
IF linescript.appshelf(ID%) = "8" THEN calc.flood ID%
IF linescript.appshelf(ID%) = "9" THEN do.looptest ID%
IF linescript.appshelf(ID%) = "10" THEN do.multiloop ID%
IF linescript.appshelf(ID%) = "11" THEN display.date ID%, 2, 30
GOTO endsubscr
runfile:
filehandle.appshelf(ID%) = FREEFILE
OPEN file.appshelf(ID%) FOR BINARY AS filehandle.appshelf(ID%)
IF LOF(filehandle.appshelf(ID%)) = 0 THEN CLOSE filehandle.appshelf(ID%): KILL file.appshelf(ID%)
GET filehandle.appshelf(ID%), , tempvar
IF tempvar = 1 THEN disp.time ID%, 1, 1
CLOSE filehandle.appshelf(ID%)
GOTO endsubscr
endsubscr:
END SUB
The line of code in bold is the one we added and we are ready to test. So run the file and at the
command line type "date", it doesn't matter what case you tpye, because the CMD sub will
automaticly convert it to uppercase.
Now that we see it has worked, mess a bit around, try to run 6 processes at once, like:
Chronos
Calc
doloop
domulti
date
and if you watched it closely, you must have noticed the speed of doloop and domulti has
seriously slowed down, this is because we update the date constantly, i know you only have
to display the date once every day, but if you do a cls, it will disappear. so therefore we are
going to use the chronstat function, this function does the following thing, it updates the screen
once every second. so we don't lose any valuable process time.
SUB display.date (ID%,X%,Y%)
loopy.appshelf(ID%) = 0
IF chrono.check(ID%, 0) = 1 THEN
LOCATE X%,Y%:PRINT DATE$
END IF
END
The lines in bold where added. So what this means is: If chrono.check returns that I still have to
refresh, then do the code.
Congratulations, you have made your first MPC application.
Loops, loops and more loops!!
Global variables!
Because we go out of the sub while it's still looping, we must use global variables. To make
it easy, I created 2 global arrays global.integer(ID%,15) global.string(ID%,15). these are arrays
which can hold 16 variables. If you wich you can always add more to them in the main program.
The hardest thing to figure out was how to do the loops. because if you do a loop just like you
are used to do, it would stuck the system right?
I will demonstrate this with an existing sub called the doloop sub.
SUB do.looptest (ID%)
loopy.appshelf(ID%) = 0
IF type.appshelf(ID%) = 1 THEN GOTO loopingtheloop
PRINT "Starting loop"
global.integer(ID%, 1) = 0
loopingtheloop:
a% = global.integer(ID%, 1)
IF a% > 1000 THEN a% = 0 ELSE a% = a% + 1
LOCATE 28, 30: PRINT "looptest: loop " + STR$(a%)
type.appshelf(ID%) = 1
global.integer(ID%, 1) = a%
END SUB
If we have just one loop the following technique is used. The type of the appshelf type.appshelf(ID%)
just holds a variable telling the sub that has already entered the loop. how do you ask? Almost at the
end of the sub you see: type.appshelf(ID%) = 1, this is an indication that the sub was already in the
loop, so if the sub is accessed again by the core, then it jumps to the loopingtheloop label.
This was easy, now something more difficult. multi loops. More than 1 loop in the sub. (shiver shiver)
SUB do.multiloop (ID%)
loopy.appshelf(ID%) = 0
IF type.appshelf(ID%) = 1 THEN
SELECT CASE loopindex.appshelf(ID%, 1) 'in what loop where we
CASE 1
GOTO loop1
CASE 2
GOTO loop2
END SELECT
END IF
LOCATE 23, 1: PRINT "Starting multiloop " + TIME$
global.integer(ID%, 1) = 0
LOCATE 24, 1: PRINT "Start loop 1 at " + TIME$
loop1:
loopindex.appshelf(ID%, 1) = 1 'say that you entered loop 1
loopindex.appshelf(ID%, 0) = 1 'say that the loop isn't done yet
a% = global.integer(ID%, 1)
IF a% > 999 THEN a% = -1 ELSE a% = a% + 1 'our goal, if a% is over 1000 then give the loop end instruction
LOCATE 25, 1: PRINT "looping 1: loop " + STR$(a%)
type.appshelf(ID%) = 1
global.integer(ID%, 1) = a%
IF global.integer(ID%, 1) = -1 THEN loopindex.appshelf(ID%, 0) = 0 'if our goal is achieved, then go out of loop1
IF loopindex.appshelf(ID%, 0) = 1 THEN GOTO domultiloopend
LOCATE 26, 1: PRINT "Start loop 2 at " + TIME$
global.integer(ID%, 0) = 0
loop2:
loopindex.appshelf(ID%, 1) = 2
loopindex.appshelf(ID%, 0) = 1
a% = global.integer(ID%, 1)
IF a% > 999 THEN a% = -1 ELSE a% = a% + 1
LOCATE 27, 1: PRINT "looping 2: loop " + STR$(a%)
type.appshelf(ID%) = 1
global.integer(ID%, 1) = a%
IF global.integer(ID%, 1) = -1 THEN loopindex.appshelf(ID%, 0) = 0 'if our goal is achieved, then go out of loop2
IF loopindex.appshelf(ID%, 0) = 1 THEN GOTO domultiloopend
finish.appshelf(ID%) = 1
LOCATE 28, 1: PRINT "Loops done at " + TIME$
domultiloopend:
END SUB
Thus, for every loop, you create a label, and at the end of the sub also a label. A little tip, if you use
endsublabel or something and use it in every sub, QB will complain, because the label is also somewhere else,
what I do is use the subname without special characters and add "end" to it, and thats my subend label.
We start by checking if the the code before the first loop is done by checking the variable type.appshelf(ID%).
Then if this is the case we look at what it did last before going back to the systemcycle. we check the
variables loopindex.appshelf(ID%, 1) and loopindex.appshelf(ID%, 0), if (ID%,1) = what loop where we in,
(ID%,0) = where we done? To end the loop, we do the following,
IF global.integer(ID%, 1) = -1 THEN loopindex.appshelf(ID%, 0) = 0 'if our goal is achieved, then go out of loop1
IF loopindex.appshelf(ID%, 0) = 1 THEN GOTO domultiloopend
This means, if (in this case global integer (ID%, 1) = -1 ) our goal is achieved, set the loopindex variable to completed
(loopindex.appshelf(ID%,0) = 0).
after the las loop we say the process is finished, unless you don't want it to finish, then you leave that
line of code out of the source and set variables loopindex.appshelf(ID%,0) & loopindex.appshelf(ID%,1) to 0.
What if i wanted to do a FOR loop?
I'm just gonna give you an example, the rest is like in the looping examples above.
SUB calc.flood (ID%)
loopy.appshelf(ID%) = 0
storeloc (ID%)
IF type.appshelf(ID%) = 1 THEN GOTO calcfloodloop
PRINT "Calc Flood start"
global.integer(ID%, 1) = 0
'FOR an% = 1 TO 32000
calcfloodloop:
global.integer(ID%, 1) = global.integer(ID%, 1) + 1
add! = (RND * 255) * (RND * 255)
bdd! = (RND * 255) * (RND * 255)
LOCATE 21, 1: PRINT "Random calculating test: ", add!
LOCATE 22, 1: PRINT "Random calculating test: ", bdd!
LOCATE 23, 1: PRINT "Loop: ", global.integer(ID%, 1)
type.appshelf(ID%) = 1
'NEXT
IF global.integer(ID%, 1) <> 2300 THEN GOTO endsubcalcflood
finish.appshelf(ID%) = 1
restoreloc (ID%)
endsubcalcflood:
END SUB
I marked the important things once more so you don't have to break your head looking for them.
Chapter 3
The interesting parts: Technical documentation
Functions & Subs
do.multiloop (ID%) Multiple loop example
do.looptest (ID%) Looping test
display.chronos (ID%) Display the chronos trigger for refreshing
chrono.check% (ID%, m%) Function that checks if an process may refresh
nano.chrono () The chrono sub for refrshing (originaly in nano seconds)
storeloc (ID%) Store the cursorlocation
restoreloc (ID%) Restore the cursor location
screen.erase (x1%, y1%, x2%, y2%) Erase text screen from X1 to Y2
display.processu (ID%, x%, y%) Display the running processes (updated - TASKMON)
calc.flood (ID%) Calculation test
flood.kernel (loops%, akk$) Add process flooding (for testing only, isn't usefull)
display.variables (ID%) Display the process variables
waitforkey () Waits for a key in a sub, while systemidle keeps running
display.process (x%, y%) Display a list of current running processes (not updated)
RunningID% () Used by display process
LastID% () Returns the highest ID used
CMD (ID%) Built in command shell
script.appshelf (ID%) system scripting sub
erase.appshelf (ID%) erase process variables
add.process% (file$, script$, name$, user%) add a process to the system
check.appshelf% (ID%) check the appshelf for kill, finish or add requests
graphgarbage (x%, y%, x2%, y2%, m%) Draw some graphical garbage (used in earlier versions)
systemidle () The main sub wich handles everything
disp.time (ID%, x%, y%) Display the time
Sinput (Inp$, Prompt$, Row%, Col%, Length%, Fore%, Back%, cursor%) Input a string
FreeID% () Returns the first free ID
Variables
chronos AS INTEGER Chronos variable (was used in earlier versions, removed)
curx(255) AS INTEGER used for storing the cursor position
cury(255) AS INTEGER same as curx
chrono.trigger AS INTEGER refresh trigger variable
chronstat.appshelf(255) AS INTEGER process refresh trigger
filehandle.appshelf(255) AS INTEGER process filehandle for the script file
loopy.appshelf(255) AS INTEGER process looping by itself? 1 = yes, 0 = let system loop it
run.appshelf(255) AS INTEGER process does it need to be started
name.appshelf(255) AS STRING process name
user.appshelf(255) AS INTEGER process user type
active.appshelf(255) AS INTEGER process is active? 1 = yes 0 = no
finish.appshelf(255) AS INTEGER process is finished? 1 = yes 0 = no
task.appshelf(255) AS INTEGER process need to do something? used by systemidle
init.appshelf(255) AS INTEGER process confirms id register (used by FreeID)
file.appshelf(255) AS STRING process script file
linescript.appshelf(255) AS STRING process if no scriptfile do this codeline
kill.appshelf(255) AS INTEGER process kill request
type.appshelf(255) AS INTEGER process type (used for looping see chapter 2)
chronos.appshelf(255) AS INTEGER process chronos variable
chronosstart AS INTEGER used for nano.chrono
loopindex.appshelf(255, 1) AS INTEGER process loop state (ID%, 0) = is loop done? (ID%, 1) = what loop
global.integer(255, 10) AS INTEGER global integers (ID%, integern%)
global.string(255, 10) AS STRING global stings (ID%, stringn%)
The main routine
active.appshelf(0) = 1 'systemcore
'ON ERROR GOTO errhandler
'OPEN "c:\boot.cfg" FOR INPUT AS 1
'IF LOF(1) = 0 THEN PRINT "boot.cfg is missing": CLOSE #1: KILL "boot.cfg": END
'LINE INPUT #1, Greetingmessage$
'PRINT Greetingmessage$
'LINE INPUT #1, shellname$
'PRINT "shell: ", shellname$
'SLEEP 'sleep for debugging purpouses
'xcuteshellx for afterworks
'we are going to use a normal sub for testing, the built in command
chronosstart% = VAL(RIGHT$(TIME$, 1))
shelname$ = "Built-in Command Shell"
a% = add.process("", "3", shellname$, 0)
'a% = add.process("", "2", "Clock 3", 1)
CLOSE #1
SCREEN 12
DO
systemidle
'LOCATE 25, 1: PRINT "Next free ID", FreeID% used for debugging in earlier versions
LOOP WHILE active.appshelf(0) = 1 'this will only work if you kill the process and exit CMD
END
errhandler:
PRINT "Error while booting"
END
Conclusion
This is my first beat release, and my first public release, the source is a little crappy, but
I expect next version will be cleaned up, varialbes that aren't used removed etc,...
Hope this article/tutorial was any good, Have fun.
Nick Verlinden
nick@zatlap.be
A Test Tour in MPC
Start up MULTI.EXE
you see the commandline.
Type in prc
You get to see something like this:
Running Processes:
Processes: 1
Name: Built-In CMD Shell ID: 1 User: System
erase the screen by typing cls
now type doloop
type taskmon
you should see a screen like the prc screen, but it keeps updating
to test this kill the process doloop
so look at the process ID in taskmon and type:
kill (id number here)
did you see the task monitor updating? removing the doloop process?
this was probably a success.
type add 6
this is the internal clock, i didn't give it a command name for some reason.
if you read the programmers manual you could try to set a command name for the clock
look at taskmon the time process is also active
this was our little tour, i'l give you a short list of built-in commands:
add add a process with linescript ...
1 = clock 1 only for testing
2 = clock 2 only for testing
3 = CMD open another CMD shell
4 = clock 3 only for testing
5 = calc.flood calculation flood for testing process slow down
6 = taskmon
7 = chronos monitor display chronos variables updated
8 = calc.flood no difference with 5
9 = doloop test single loop
10 = multiloop multiple loop test
- add does only work with a 1 digit argument so you can not add 10, because then he will add 0
- you can only add from 1 to 9
chronos <>
displays the chronos variables
prc <>
displays the current processes running (not updated)
taskmon <>
displays the processes running (constantly updated until kill)
var <ID>
displays the process variables for that ID
doloop <>
infinite loop
domulti <>
does 2 different loops
calc <>
does random calculating for ...allot of loops
flood <Number of processes>
adds as many processes as given
kill <ID>
kills the process with that ID
Tour END
Download Multiprocessing Core for QB 4.5 and these articles: Multi.zip
Modular Programming Versus Object Oriented Programming
(The Good, The Bad and the Ugly)
An Article Written by Stéphane Richard (Mystikshadows)
INTRODUCTION:
I'm sure some of your, by now, might be saying "what is that all about?". Allow me to begin this with
a brief history of why I decided to write on this subject. You see, for decades already, when I hear
talks about programming concepts and paradigms, It seems that Modular Programming techniques and object
Oriented Programming have been under somekind of comparison by developers all around the world. A hidden
feud between the two serving the soul purpose of boasting the advantages of one over the other. Also,
It seems that with time, O.O.P. took on a very different role, one that radically changes the way newcomers
to the world of development see and understand the concept. However, if you go on C forums, QB forums, and
other languages too, and talk about O.O.P. you might be surprised at the answers you get from those
communities.
Basically, these two items are what motivated me to write about the subject in question. NOte that the
contents of this document represent my own point of view, my personal understanding of the concepts and
my thoughts on what should be what. But i have seen the evolution of Modular Programming and Object Oriented
Programming from their very beginning, I've also seen all the deviation that these programming methods
took in the course of their evolution. I will be explaining these methods and share my views and insight
on where each method can provide the best advantages on a project. This will give you the information you
need to understand the rest of the document where I will be sharing what has been said about these methods
and show you where the deviations that was bestowed upon the O.O.P. paradigm changed everything that O.O.P.
is known as today.
WHAT IS MODULAR PROGRAMMING:
Modular (or Procedural) programming is a coding method that entails the use of routines, sub routines and
functions in order to organize and execute specific sets of instructions pertaining to a given task to be
done. The main rule of thumb in this technique is that if a set of instructions, that perform a specific
task or calculation, will be called several times, it should be moved to a subroutine (if it does not return
a value) or a function (if it does return a value) and called from the needed other parts of the program.
Typically, to create a successful modular structured approach to solve a problem, you need to define the problem in terms of
what actions or calculations the program needs to do in order to perform the task defined in the problem. You also need to see
if there is any special connection between procedures and functions to establish an execution order for them. The other
concept here is that if a subroutine or a function is quite big, it is probably due for a refactoring into two or more
sub routines. This is essentially how modular programming manages the complexity of a program by breaking it down
into smaller, simpler, more managable sections of code.
Over the years, structured programming has been given more than one coding style and as such gives a good foundation
to adapt the programming method to fit one's minding. By that I mean that depending on a developer's background he or
she might like to organize their modules, procedures and functions based on functional grouping (all string manipulation
functions go in one module, all datatypes go in another module, all constants in yet another module, this is often
the type of organization I like to follow as well. Others might prefer to organize their modular approach based on an
entity structure (somewhat closer to O.O.P.). For example, all datatypes, procedures and functions that affect an employee's
information goes in one module, all inventory datatypes and functionality goes in another module. This is one of the great
advantages to the modular programming approach in that it allows to organize the code in a way that fits the developer's
way of thinking. When you think about it, it can be a very strong point since everyone thinks in very different ways
but everyone needs to be able to define their problem and bring solutions based on how they would solve them manually.
WHAT IS OBJECT ORIENTED PROGRAMMING:
Object Oriented Programming is a coding method that entails the use of objects and their relationships in order to
describe, programmatically, the problem to be solved. The classic definition of O.O.P. was based on three founding pillars
which were Encapsulation, Inheritance and Polymorphism. Here is a brief explanation of these founding blocks.
- Encapsulation:
This term defines the fact that both the data, and the functionaly that could affect or display that data are both included
under a unified name (the object name itself). In the classic definition, the data elements (or properties of the object) are
not available to the outside world directly. Instead, methods would be created to give access to these values outside
of the object. Quickly, most languaged that supported Object Oriented Programming added the ability to declare properties as
being public or private which took away from the original definition of keep that data private to the object only.
- Inheritance:
This feature allows developers to define objects in a hierarchy much like a taxonomy chart (like the animal kingdom classification chart).
Each level of the hierarchy defines a more specific object than the parent level. Each level inherits all the properties and methods
of it's parent object and at that point you define the more specific properties and methods need by the new level
of object you created.
- Polymorphism:
This is a very fancy term to say that at any level of an object hierarchy each object could have a method of the same name and because
of the level at which the method resides in, it could know which of the procedures or functions to call. Hence you could have a Shape
object that has a Draw method. Then you could define a Circle, Square and Triangle object as Shape objects and override the
Draw method to draw specifically a Circle, Square or Triangle method respectively. All 4 objects would then have a Draw method
but only the right method for the right object would be called.
In the classic definition of O.O.P. These founding blocks were created because of the birth of a need for code reusability without simply cut
and pasting existing code into a new module. Hence you could create an object or a hierarchy of objects that pertained to a specific role. then
give the compiled version of that object as a library to another person who could then create his own objects as being part of the originally
defined hierarchy. Today, two new pillars have been added to the definition of O.O.P. They are Interface and Abstraction. Here are their
definitions.
- Interface:
This was added to O.O.P. in the goal to allow developers to provide an object template to control the access and definition of objects. An
interface is simply a list of fixed method names that any object defined as being of this interface type must implement in order to be qualified
as a valid object of the type the interface implies. This basically gave developers the ability to strictly control the naming conventions used
in their objects as well as objects created by other developers designed to work in the current object model.
- Abstraction:
As popular as this term now is in the world of Object Oriented Programming, this essentially goes against all programming techniques. Abstraction
is the ability to not need to pay attention to the type of objects that are bring used if the developer sees fit to do so. For example, a Dog could
be treated as a dog probably most of the time, but of you have wolves, foxes and other similar dog like animals in your hierarchy, you could treat
them all as Canidae class objects if you'd need to apply changes to all 3 animal types (provided these animals are of declared as Canidae type objects
first. From Abstraction was born the need for the know infamous Variant datatype and the ability to declare variable as the ANY datatype.
Essentially, O.O.P. is an evolving standard that adapts to new needed concepts as they are needed. This can be fun in some cases, but a real curse in
most other cases. These last two pillars also created the concept of black box and white box programming techniques. The classic object was White box (which means
that levels of the hierarchy needed to know what came at the parent level in order to be able to perform its task. In White Box development, a hierarchy defined
levels of specializations of objects in a hierarchy where objects in a lower level had more refined programming compared to it's parent. In Black Box development,
Each level of the hierarchy tends to define containment rather than refinement. For example: The white box would state that a dog is a specialized (or refined)
type of Canidae. In Black box, a Canidae has a dog (and a wolf, and a fox as it's sub components. This can lead to some serious conflicts in my opinion, which i will
share later in this document. For now, let's compare Modular Programming and Object Oriented Programming versus a typical problem scenario to get a glimpse of the
real differences of both methods.
METHOD APPROACH COMPARISON:
The Scenario:
The scenario I'll be using is the following. The boss comes to see you and asks you: "I would like a program that can save information on the employees to a file, I would like to be able
to enter the Employee's ID, his name, address, city, state, zip code, telephone number, email and hourly rate and it should
also be able to to retrieve that information based on one or more criteria that I would enter in different fields. I would like to print that information so I can put the employee information
in a physical file. The employee should be able to to enter the time they arrive at,
the time the leave and come back from lunch and the time they leave at the end of the day in a timesheet program. The program should be able to calculate how many hours they have
worked that week, the gross pay they have gotten and the amount of overtime they worked (as well as what monetary value the overtime amounts to. Employees are paid 1 1/2 times their
hourly rate for any hours over the regular 40 hours a week and they are paid twice their rate on any holiday. Everything should be saved and retrievable on a per employee basis. I also
want weekly, monthly and yearly detailed and summary reports on all this information for all or one of the employees at a time."
The Modular Programming Approach:
In the modular programming approach, the verbs in the problem description are the ones considered first. Typically, these verbs represent the work to be done and therefore the likely subroutines
that we would have to implement in order to solve the problem. The names in the description represent the information (variables and datatypes) that will will be acting on or producing at the end.
Modular programming is based on three things, which are: 1. The information needed before the process can start, 2. The work to be done with that information and 3. The expected output of a procedure.
We will here answer these questions as per our scenario above:
- What Information Is Needed:
By reading the problem description, we know already the information we need about the employee, so I won't define them here. However, we need to define the information about the
timesheet itself. The timesheet should have the curent date, the start time, the lunch time start, the lunch time end, and the days end start. All this information should be linked
with the employee itself by adding an EmployeeID field to our definition since each employee will be entering their own time.
- What Is The work to be done with that information:
Again based on the problem description, The program should allow us to enter and save employee information to a master employee file. It should also allow entering and saving of timesheet data
into a timesheet database file. When needed, the system should allow to enter an employee ID or Name and show the user the week's total hours worked, gross earnings, the number of hours in
overtime and the earnings from that as well. it should calculate the total hours and the total amount earned for that current week. The report should allow the user to specify a range of date
for either a week, a month or the whole fiscal year and an optional employee ID to print out the payroll information for either the specified employee or all the employees (if none were entered).
- What Is The Expected Output(s):
The first out is the employee's information that needs to be printable on paper. it is mentionned and should be coded for. The other printable information that are stated are the weekly, monthly
and yearly reports on one or all the employees. There is another piece of printed output that is understated here but not literally mentionned, the timesheets themselves. It makes sense to give an
employee his weekly timesheet at the end of the week and/or for the employer to request an employee's timesheet at the end of the week. So we would typically implement a procedure to print timesheet
information on request.
As you can see, the modular approach is closely related to the functionality needed in the problem description. You think in terms of what needs to be done and usually can pretty quickly devise a workable
complete solution to a problem by consecutively answering these three questions (some of these answer may require that you breakdown the system into smaller answers to a subset of these three question depending
on how complex the system gets. This breaking down into smaller more specific procedures and functions is how Modular Programming offers to manage the complexity of a program.
The Object Oriented Approach:
In Object Oriented Programming, the names, not the verbs, are the first to be considered because in O.O.P. the first task is to define entities, not actions. O.O.P. starts by defining the players (or actors if you will)
of a given scene (the problem) and them proceeds to defining how the actors are described (the properties) and what the actors can do (the methods). Once all these are defined for all playing actors, then the scene
(the main part of the program controls what each players has and what it does. Only when you are defining the methods of the object can you actually start answering the same three questions that the modular approach
lets you define right from the start. Again, as we did in the modular approach, I will define the same problem description using the Object Oriented Programming Approach instead of the Modular Approach I used previously:
The Entities:
By reading the problem description. We can clearly indentify three entities. The Employees, the Timesheet and the reporting system. This is how O.O.P. problem solving begins. You need to identify these entities
first and the define how you describe the object as well as define what the object can do. So let's take each entity and define them so you can see how things work:
- The Employee Entity:
The Employee is the main actor of the scene. Every other entity in the model revolves around what
the employee is and what it can do. In any object model you define, it's always important to identify
this key player because it is at the center of any object relationships that can exist. Here are the
defining attributes (properties) and Related Functionality (The Methods) of the Employee Entity.
- Defining Attributes:
As mentionned in the description, the Employee entity will need an EmployeeID, his name, address, city, state, zip code, telephone number, email and hourly rate attributes.
- Related Functionality:
The Employee needs to be able to do several things as far as it's defining attributes go as well as the ability to call the functionality of the other entities for timekeeping and
and calculations. As such, the methods needed will be. EnterEmployee, SaveEmployee, LoadEmployee, FindEmployee and PrintEmployee.
- The TimeSheet Entity:
The TimeSheet Entity should be made to work a week based format where all the days are there so that it can be easy to get a quick overview of
what the week is like currently. We will add a method to our object to make sure that an employee's weekly data is completely entered before we
go ahead and print the timesheets just as a precaution because of the importance of the data that is being handled.
- Defining Attributes:
When you think of a timesheet, it doesn't take too long to determine the general information that you would need. The properties are:
EmployeeID, DayOfWeek, DayDate, StartTime, LunchStartTime, LunchEndTime, EndOfDayTime. EmployeeID is needed to connect a timesheet record to
an employee record in the master employee data file. The rest of the properties specifically relate to the TimeSheet Entity itself.
- Related Functionality:
As mentionned in the problem description, the TimeSheet entity will need to perform several types of actions. The names of the methods described here
should help state clearly what the methods which helps make the object definition that much clearer. Asu such, here are these methods:
GetTimeSheetData, SaveTimeSheetData, LoadTimeSheetData, PrintTimeSheetData, WeeklDataCompleted, PrintWeeklyTimeSheet, CalculateRegularHours,
CalculateOverTimeHours, CalculateHolidayHours, CalculateRegularAmount, CalculateHolidayAmount
- The ReportingSystem Entity:
The ReportingSystem is present because on an entity based problem solving approach, every method needs to find it's place withing an object model. In most cases, printing related functionality is very often isolated into a seperate entity and sometimes even an independant application (so that it can be executed on a seperate system on the network and print the report while users can continue to do their other activities uninterrupted by the printing process).
- Defining Attributes:
Since the ReportingSystem entity creates no data files, all it needs is three attributes to perform it's task. These attributes are the EmployeeID, a StartDate and an EndDate properties so that
it can accumulate all the TimeSheetRecords that fall between these two dates.
- Related Functionality:
Ultimately, we could have provided all printing functionality in the ReportingSystem entity, which means that the printing of the Employee Data could have also been added
as a related functionality. For the sake of this example, I isolated them for the sake of keeping the objects as isolated and independant as possible. As such, this engine only
has one method. PrintReport which will print either a weekly, a monthly or a yearly report on the timesheet data for either an employee in particular or all the employees
in the data file.
As you can see, the Object Oriented Approach to problem solving is quite different from the Modular Approach. With all this information you now have on the two methods, you might be
wondering if there are certain projects, or certain parts of a big project that could benefit from the Modular Approach and likewise for the Object Oriented Approach. Is there situations
where you would be better off using one method over another. In this next section, I will discuss this subject, based on my own personal experiences with both methods.
WHEN ONE METHOD SHOULD BE USED OVER ANOTHER:
If we take into consideration both methods used in the example above. We can see that both of them managed to define the problem, and possible organization adequately. In their own domain,
we can say that they were both as successful as the other in doing what they are supposed to do. So where and when can and should you use one method over another? My experience has shown me
that the best way to answer that question is to go by development domains they each have their own best way of describing their needs. Let's take a few examples industries to see how to select
the best method.
- Any Mathematic Oriented Industries:
In these we can include financial institutions, banks, accountant firms, statistical analysis firms and other related domain where the formulas prevail over the method. In these particular cases,
chances are that problems will be defined based on the specific calculations that need to be performed. Since in programming, calculations translate to functions in code, the Modular Programming approach
to problem solving can usually relate more closely to the description of the problem at hand. Therefore if you are working for such a firm, or you want to create an application for that specific industry,
The modular approach would be the best way by which you can present your project to the people that know the industry well in such a way that they will understand you clearly and faster.
- Most Science Related Industries:
In here we can throw any chemical engineering, Physics based Research and Development and any other related industries that depend on specific methods and order of things in order to perform at their
best. Again in these industries, formulas are pretty important when describing the problem but usually not as much as when describing the specific order in which events and
calculations need to happen. There's nothing quite like Modular Programming approach when describing an order in execution step that is required by the domain you are developing in and must be followed
flawlessly. Therefore, people in this industry will tend to talk in groups of related steps needed to accomplish a task.
- Database Native Industries:
In this category Falls alot of different businesses. For example Inventory management businesses, call management and many communication related industries, essentially, any business who's business is related to data.
Database Software has evolved, much like O.O.P. in order to answer the new, growing, more complex database needs of these companies. So today, when you encounter one of these industries in your career, chances are, when
they describe a problem, they will be describing the problem based on Tables in a database, relationships between the tables and the role each table plays within the whole database structure. Also, when they give names
to their tables, they will more than likely describe them precisely as they would an object, a table will represent an object, it's fields will represent the object properties. Because of this high resemblence to object
oriented programming methods, O.O.P. stands ahead of modular program as far as implementing a solution that will make sense to the way people from these specific companies conprehend the way they do business.
- Document Driven Industries:
Lawyer firms, sales force companies, publicity related enterprises all fall in this category. Even though these industries would probably need databases and talk about them like database native industries, To the people
of these industries don't rely on a particular table, but more on everything that pertains to a particular client. When these people describe their needs, they will typically talk of a file in which different type of
information (usually forms and contracts) need to all be part of the file when they leave. This is true whether they are talking about a physical file or an electronic data retrieval system (such as data replication systems).
O.O.P. tends to play this role well. However I can advise that very specific names to the objects will be required. Especially as far as lawyer firms go since to them each form has a name, a number, something that makes the
forms and contracts unique in contents and purpose. They typically worked hard to create their standards and procedure and will expect their standards to be followed even in an application.
- Multimedia And Entertaiment Industries:
Everything that pertains to entertainment. For example, Music software designers, Recording studios, game designers, even book publishers, and video production groups. In these industries, database are not the primary concern,
they are more concerned with the product they are creating for their customer. And you'll probably notice that they explained things always based on the type of work they do, who they do it for and what elements they need to do their
job right as per the work to be done. All in all, these industries today all talk in a very Object Oriented way because all they work with are physical things or physical representation of different things, especially the gaming industry
since by today's standard the gaming industry is all about 3D worlds and 3D object representations. So when they want you to develop a game module for a specific game, chances are, they will describe them to you in terms of an object you
will be adding methods to or creating from scratch. Of course object oriented is better suited, however, it's important to know that one of the reasons why O.O.P. was so propagated in these industries isn't because Modular Programming couldn't have
done job, but rather a simple choice to go the O.O.P. way when they created DirectX and OpenGL standards and specifications. If OpenGL was created using the modular programming approach instead, today, Modular Programming would have been the gaming
standard.
This covers the industry and which method you're more likely to want to employ when developing (and presenting) a solution to the people that work in these respective industries. There is another factor that can be a very big player in your
decision to use one method over another. That factor is one of the size of a project and hence it's complexity. There are many cases where even a program, for an entirely O.O.P. oriented industry like Multimedia and Entertainment, just doesn't need
O.O.P. or would fail to take advantage of the O.O.P. approach to bring a solution to that particular problem. Likewise, O.O.P. could very well be the only viable solution to a problem brought forth by industries that have never needed O.O.P. before. It really all
depends on the way they can explain these problems based on what they know of their industry. One last factor could be that the company you are developing for already have tools and do not wish to purchase tools to accomodate for the missing method. In other words,
companies could very well impose their development methods and expect you to be able to arrive at a solution using their method whether it's suited for the task or not. In those case you just need to make the best of what you have.
These represent how I would deal with problems in these specific industries. I'll take the time to see how a concept can best be described to
the users of the program I am making and if the description is based on objects, unless there is a restriction that stops me from doing so, I will
use an O.O.P. approach especially when you are creating an entirely new project. When you think about it, there isn't just the program that you are
making to consider but also how easy your solution will be for the users to understand and use. This means that you have to take the time, in making your
decision, to see what kind of user you are dealing with to see how they might react to one or the other of the explanation methods and based on the findings
of that little research, use the method that can be thought the fastest and easiest.
WHERE OBJECT ORIENTED PROGRAMMING FAILED:
When you talk about O.O.P. today, you'll hear some very different explanations by different software professionals. Since O.O.P. is found on the 5 pillars I mentionned about, how can these answers be so
diverse and, in some cases, so out of touch with each other? The first answer I have to bring here is that depending on when developers started learning O.O.P. they were given some very different notions
on what exactly O.O.P. is and how to efficiently use it for problem solving.
One of these new notions arrived when Java hit the mainstream programming industry. Which suddently told you that everything imaginable in programming is now an object including strings, integer and other datatypes. hence the base of all
programming should be the object. The problem with this notion is that it's true only for languages that are designed around the same concept as Java where everything you can create is an object. This does not today
constitute the majority of the popular languages you can use today. When you think about it, a datatype has no reason to be an object simply because of the way a compiler organizes memory. An object has an overhead
that would represent a major waist of memory compared to storing the classic 4 bytes for integers. All these little things is what makes Java so slow and a perfect example of sloppy bloated code waiting for a faster
processor to surface so it can make it look faster.
Another one of the confusions in O.O.P. definitions arrived when Objects Modelling techniques like U.M.L. (Unified Modeling Language) made surface. U.M.L. in itself is not a bad approach at all in problem solving. However, today, alot of
what defines U.M.L. is confused, or atleast stated when talking about O.O.P. Often when I talk to people, they will mention such notions as
agreggations and composition. The problem with this is that any language that can do O.O.P. doesn't have an aggregation or composition construct per
se. But these people say that they do alot of aggregations and compositions when they develop. I then have to explain to them that these are object modeling
principles and have no direct equivalent in the language itself. Aggregation denotes a whole/part relationship between objects. For example a Circle is the whole object and a point, is part of a circle objects this is created as an
aggregation of two objects. A Composition can be used to create a relationship between objects too but it has the added ability to have a source and a destination (Circle knows about Point, but Point doesn't know anything about circle).
These are Object Modelling principles and cannot be directly coded in a language. but when translating the principle to the selected programming language, it could mean that
the module that defines Circle will have an #include "point.h". But it does not mean that because this include statement is in the Circle Module that you have created an aggregation necessarily.
OBJECT ORIENTED MYTHS:
If you have been to forums and message boards that compare and debate modular programming and object oriented programming, you might have noticed that many claim O.O.P. is the only intelligent methods and start enumerating reasons that have
absolutely no direct relationship to O.O.P. I've seen these too many times and it's a shame to see most of them are enumerated in an effort to bring down modular program and try to boast O.O.P. as a better approach. I will be listing here
some of the more popular myths about O.O.P. that I have seen and tell you what I have experienced in regards to the myths themselves.
- Object Oriented Programming is closer to how people think.
The first thing I can say about this is to take a look at the industries I've mentionned previously in this article and notice how the people working in these
industries typically think. Some people are simply better suited to think in terms of modular programming, others seem to think that O.O.P. really does offer
a clearer approach that as human beings, they can more naturally follow. But the truth of the matter is that everything depends alot on the working experiences
of the individuals. Each method, if you were to do a survey, would probably be close to equal in results.
- Object Oriented Programming makes debugging quicker and easier.
I'm sure this isn't the first time you've heard of this myth. The previous myth is largely responsible for the fact that people believe that debugging O.O.P.
based programs is easier and quicker to locate and fix a bug. The truth of the matter is, when a bug does occur it will usually do so either in one of the methods of
and object which in most cases is equivalent to a procedure or a function. If you have implemented an elaborate hierarchy of objects, making proper use of polymorphism
you might find yourself looking through more than one procedure called Draw and that could go double if Abstraction was used as well In essence, debugging is not about a programming
method per se. It is rather about what you return to the user in your error management routines that can help locate a bug quickly or not. Once you have located the bug fixing it
in either methods is equally easy and fast.
- Object Oriented Programming gives you a better organization of your code.
This to me is debatable. Atleast I wouldn't phrase it this way. I would choose to say: "O.O.P. forces you to abide by a given standard" which results in all your objects
being defined and implemented the same way. Differente developers visualize and comprehend programming concepts in very different ways. Some can instinctively break a process into
a workable set of procedures and functions but just can't relate to the Object Oriented Approach simply because they skip that step of definition to go directly to what actions need to be performed.
Modular Programming allows you to organize your code pretty much anyway you want and when you think about that concept. I could easily organize a user defined type (or more) and a set of procedures that
display or manipulate elements of that datatype in such a way that it can be made to look quite close to how I would have done it using the Object Oriented approach.
- Object Oriented Programming is more powerful than Modular Programming.
I really have to draw the line at this one. So far, in all of my 30 years of programming in both methods, I have yet to see O.O.P. be able to do anything that can't be done
in a procedural language. In my opinion, this belief is because new comers to programming take a look at what's out there and see things like OpenGL, OpenAL, DirectX, Allegro and all
"popular" engines for making the "hot" games and think to themselves: "Wow, O.O.P. can do all that? Amazing!" The problem is that the newcomers will usually stop right there. They
won't even think for a second that Modular Programming can do the same because they saw the O.O.P. version first. To that I say, just look at the METHOD APPROACH COMPARISON I did earlier
in this article. Both methods defined the problem and could bring a solution to that problem. If you took the time to do both of these methods on any programming projects you have, you'll
find that for every O.O.P. problem solving definition, there is an equal (sometimes shorter even) Modular Approach that can do the same job. This pretty much sets this myth rest on it's own.
I do have to say however that there are some myths that I found to be true however, again based on my own experience. And when you think about the reasons I give here, you'll
find it hard to see it differently. This told me that O.O.P. can have it's specific place. Here are the two most widespread
myths that have proven themselves to me as being true.
- Object Oriented Programming is ideal for simulation projects:
As you know, a simulation is a program that reproduces the some parts of the real world. As such, it makes perfect sense to represent the real world using an object model. In a simulation you are
also likely to see relationships between objects as well as interaction among these objects. O.O.P. is definitaly adapted for this kind of software development and can more closely mimic the real world
object it is trying to simulate. This is true for both outside objects reacting and interacting with each other, or to explain and define all the inner components that make up a bigger more complex object. There's no
denying that O.O.P. can be wisely used here for all these reasons. Note that Modular programming could do the job as well. But when you think about it, it would be hard to use the modular approach to explain
objects, their properties and their methods as well as their relationships to other objects in a procedural way. It could be done, but in this particular case, it would be longer to do when you'd get to explaining
the relationship between objects or between components of an object. This is in the analysis only however, the modular code that could do what the object oriented code could wouldn't be much different in size and could
actually have a very similar coding organization in both cases.
- Object Oriented Programming is ideal for Business knowledge development:
This one today is very true, but O.O.P. itself is not the main or only reason why it is so true today. As I mentionned in the database related industries, database systems have evolved
to answer the growing needs of database administrators and businesses worldwide. As such, an Ojbect model and a database model are usually very closely related. So related in fact that
it would actually be longer to seperated the model and break them down modularly to explain their functionalities and roles. As such, This is a perfect scenario where O.O.P. really has a
distinct advantage over Modular Programming. Sure you could devise a set of procedures and functions and have them perform the designated task, however, in businesses, it is all about relationships
between business objects.
THE BOTTOM LINE:
The bottom line is quite simple. It would not be wise to decide that everything can be made from one of these methods and stick to it alone for all your programming endeavors. In some cases, O.O.P. will naturally
be able to represent a problem much more efficiently where in other cases, a modular approach could save you loads of time by being able to represent the problem much quicker, easier and cleaner than any O.O.P. model
ever could. it's important to remember that Modular Programming and Object Oriented Programming are two problem solving methods and that both are designed to bring answers to questions and solutions to problems. They
are two different means of implementing a solution and that is really all that needs to be remembered.
It's important that you remember that this article really reflect my own experiences with both problem solving methods and my own personal opinions about them. Others probably have a different point of view and may have
all the right reasons to believe them. All I can say is so far, in my 30 years of personal and professional development, my judgement on these has not failed me once. It takes good common sense and a bit of logic to make the
right decisions and opinions about them. I will finish by saying that it's not wise to destroy a problem solving method over another, they truely do have their advantages and could make your life easier if you didn't reject
either of them. It is even worse to believe what others say without knowledge. This means that if you want to form your opinions, don't read comments from anyone and believe them blindly. Give Modular Programming and Object
Oriented Programming atleast a fair chance, find a project for each and see where each method takes you. It won't be bad for your career to know when each methods has advantages so it should be time well spent on your part. Learn
them, evaluate them, compare them THEN when you have the knowledge you need, you can make a good choice.
As you now know, with all my writings, I am always opened to discussion and comments, suggestions and even debates. You can email me whenever you want to clear things that weren't clear to you when you read this. This article is the
result of my own experience with the different programming methods. Your past experiences might give you a similar or different point of view on this subject. I'd like to hear of them because I know that everyone has his or her own thoughts
on this subject, I see it every day on forums I visit. Until the next time I write, happy reading and programming no matter which method you like to use.
MystikShadows
Stéphane Richard
srichard@adaworld.com
Download a copy of this tutorial: modularversusoop.html
Implementing Line of Sight in Qbasic Games
Written by Torahteen
Introduction:
Line of Sight is often overlooked in a lot of good QBasic games. This is surprising to me, because it is both easy to implement, and it adds a good touch of realism. But there are numerous ways to put in line of sight. In this tutorial, I'm going to look at two. The circular and diamond line of sight. By the way, these work best in a tile-based game. You'll have to find some other way if you're doing a FPS, in which case these are unnecisarry. Enough ranting, let's get started.
Diamond Line of Sight
Okay, first of all, I don't know what the heck you call either of these methods. I made up the names, so if you find another name for them, it's probably correct. Anyway, the first thing we're going to implement is a diamond view system. In a diamond view system, the unit can see all of everything in a sort of diamond shape around the unit. There are two different diamonds you can do. One of them, has the points of the diamond pointing up, down, left, and right relative to the screen. The other has the points pointing in those directions relative to the unit. I'll be going over the first one, although I will give a short theory as to how you can do the other one.
Since I like to make my games modular, let's make the code into a function. We'll have the game engine call the function, passing in a map, the x and y values, the distance the unit can see, and a reference to the array we should put the final coordinates in. What I mean by final coordinates is a list of points defining what squares the unit can see. So here is our function declaration (BTW, it is not a true function, but a sub):
DECLARE SUB GetLos(map() AS MapType,x AS INTEGER, y AS INTEGER, sight AS INTEGER, result() AS PointType)
MapType should be defined somewhere in the game. But as an example, here is the MapType we'll use in this game.
TYPE MapType
mType AS BYTE
Clip AS BYTE
END TYPE
mType is the type of tile (Water, Grass, Rock), and is just an example. We'll be using the Clip status to check if a tile can be seen.
The way I will do all this, is with three nested FOR loops. The first loops iterates from the top of the diamond to the bottom. The second loop increments the width of the diamond by two for every line. The third loop goes through each square in the row. Every loop, we will check each square across the line, making sure that its clip value is false. Here is the code.
SUB GetLos(map() AS MapType, x AS INTEGER, y AS INTEGER, sight AS INTEGER, result() AS PointType))
Dim nx, ny As Integer
Dim w, d As Integer
Dim n As Integer
n = 0
w = 1
n = 1
redim preserve unitMove(n) as PointType
unitMove(n).x = x
unitMove(n).y = y
For ny = sight To -(sight) Step -1
For w = 1 To 2 * sight Step 2
For nx = -(w - x) To (w-x)
'Checks go here.
sx = nx
sy = y + ny
if sx > -1 and sx < mapWidth and sy > -1 and sy < mapHeight then
n = n + 1
Redim Preserve result(n) As PointType
unitMove(n).x = sx
unitMove(n).y = sy
end if
Next nx
Next w
Next ny
End Sub