Issue #2
March 10th, 2001



Toshihiro Horie


Welcome to issue #2 of the QB Chronicles!

Well I think the first issue was well recieved in the QB world. We got a lot of readers in the first month, and that, obviously, is a good thing. Special thanks to Jordan of Future Software for putting up the news about the first issue of the mag on his site and on QQN which helped alot (I got about 100 unique visitors form QQN alone).

Well this month we've got the second part to the XMS article, we've got an article I wrote on the basics of using the palette, which goes over such things as fading and changing colour's for your game's purposes. As well we've got a new monthly feature on rants. This month's rant gives possible reasons why people never finish their projects in QB. Also I've continued the RPG article, this month we delve more into NPC's and how to make 'em move. Check it out!

And as you've probably noticed (if not you will), the look of the mag has been changed! The first issue was sort of a simple layout and now I hope you will grow to like this design. Anyways hope you enjoy and please be sure to tell me what you think!

-Fling-master, editor of the QB Chronicles


This is obviously a new section of the mag where I'll put e-mails in general that I receive regarding the QB Chronicles. If you send me an e-mail (which is not a news submittion, or an e-mail with an article attached or something else that shouldn't be printed here) then I'll put your e-mail here with a comment or response. Here's one e-mail I recieved about issue 1:

Hi Flingmaster,
  I want to congratulate you on starting a cool new QB magazine!  The articles are well-written and shows advanced knowledge of QB and design techniques.
   I liked how you covered both medium and advanced stuff in your articles.  That's the best way to get a large QB audience.  I like the explanation then short code segment writing style, which keeps the reader involved in the program exploration.  I also like the question and answer style, in which you telepathically anticipated what the reader would want to know next.  Also, the formatting is simple and elegant, and very readable.
   Here are some minor errors I've caught in the first issue.
  1) Microsoft FrontPage 4.0 forgot to update the Letter from the Editor internal link from file:///C:/GERED/site/qbchronicles/issue1.html#letter to #letter.
  2) You don't need to do z=INT(x\y) when x, y, and z are integers.  All you need is z=x\y, which is faster and shorter.

   I wish you luck in your next issue-- I'll try hard to write a tutorial article as good as yours.


Thanks for the feedback! I'm glad you liked issue #1. I worked hard on it and wasn't sure how the QB community would take another new magazine. About the writing style I used: I like doing sort of a Q&A style article because it addresses questions the readers might have (hopefully). I also like showing code segments and not just one line of code. It sort of gives the reader an idea of how to incorporate the technique or whatever into their programs.
And thanks for picking up the error's! The first one is how I have it set up at home and, like you said, I guess Frontpage forgot to update the link. And I have no idea what I was thinking when I used INT. Thanks for picking both up! Hope you enjoy this issue!!


  • Future Software MsgBoard
  • QuickBASIC News
  • Singsong
  • Toshihiro Horie
Pure QB Intro contest
This contest being organized by Toshihiro Horie, is to improve the state of art in QuickBASIC visual and audio effects by having people compete in an Inro contest. An 'Intro' is basically a short version of a demo. Want more info? Click here. The deadline for entries is March 31st, 2001. Entries are to be sent to this address enclosed in a zip file with your name, and the source code for the intro and any other files needed. It should have an included README.TXT describing it. There's a list of rules on the official site. Check it out!


This is a cool program which is basically a "show-off" of really cool effects. It includes source code so you can see how everything's done. Check it out at this address.


Enhanced Creations++
That's right! Angelo Mottola is back with a new site! Although he still doesn't program in QB anymore. This site, Enhanced Creations++, is for his projects which are now being made in C/C++ with the library Allegro.

All his original projects (DirectQB, Wetspot, etc.) are still available for download though.


Xgmae, a cool new space shooter.
This game is actually a really cool space shooter. All you do in it is shoot asteroids, but still... I thought it was fun. Its done completely in black and white. You can take a look at it at this site. Its got alot of neat features, like multiple weapons and a multiplayer mode.


Programming Oasis Shutdown
The Programming Oasis, a site which was put together by Nightwolf was officially shutdown. This was reported on the Future Software board last month. The Programming Oasis was a huge tutorials site which had many documents on a bunch of different languages like QB, C++, Perl, VB, etc.

Nightwolf has said that he is going to be working on a new site similar to the Programming Oasis but with only tutorials. Stay tuned for more info.


Dragon Warrior For QuickBASIC
HyperRealistic Games is at work created a clone of the original Dragon Warrior for the NES. It will run in QB4.5 and will make use of the RPG QuickLib. It'll also feature a few "fixes" of sorts from the original game which'll make it easier to play. (i.e you won't have to go to the menu and select 'Stairs' to go down or up stairs) Currently I'm are looking for a few people to help out with getting the graphics, sounds, and monster stats from the original game. If you would like to help (and you must be committed to your work) then contact me. The project site will be up soon and hopefully a download will be released before the month is up!


QBasic Paradise for sale
The QBasic Paradise, a very popular QB site, has been put up for sale. Although now the current price is $0.00. If you want to keep this site going then e-mail the webmaster.


QuickBASIC Network to be updated soon
The QuickBASIC Network is going to be updated finally very soon. Jon Scott the owner of that and now the domain said that he'd be updating it in march.


Free advertising in the QB Chronicles!
Do you own a site which no one has ever heard of? Are you looking for ways to boost the amount of visitors to your site? Or are you looking to create some "hype" about your new project? Then say no more. In future issues of the QB Chronicles we will allow anybody to get free advertising in this mag. Just e-mail me and we can set something up. I would prefer that you have a banner or logo for whatever it is you're advertising, it just looks alot nicer then text.



These are the QB Chronicles editor's Top 10 downloads. These are superb programs/games which any QB'er should have. In this issue and future issues, you'll be able to vote for your favourite QB program. So submit your opinion below!

Submit your vote!

Name of program:

Rank Description
1 Future.Library
Probably the best library out there. It can do it all. Great sprite management. XMS and EMS support. Great sound handling. SVGA resolutions. And they are all fast. Get this! Now!!
2 Shadow of Power
One of the best QBRPG's out there. Fantastic graphics, Zelda-like gameplay, good sound, and a development kit all included.
3 DirectSound for QB
This (obviously) allows you to use DirectSound in your QB programs! One plus for this is that you don't have to include a setup program to setup sound settings. Get it.
4 Zeta BETA 2
A cool SVGA 3D game. Very realistic graphics, and great sound, not to mention superb gameplay. A big download but worth it!
5 DirectQB
This is still the best VGA library available. (Well second only to Future.Library) It supports EMS layers, lots of graphics, sound, disk, keyboard, etc routines. Try it today!
6 Wetspot 2
Some people might say that I shouldn't bother putting up an old game, but this one is fantastic. Great graphics, multiplayer modes, a level designer. And its FUN!! =)
7 Arrakis
Somewhat old now but one of few strategy games. This ones complete too! Features a RMG, great AI, graphics, sound and gameplay.
8 Ultimate Super Stack
A way-cool puzzle game with lots of levels. The graphics are really good too.
9 Dynamic
Great space-shooter with good graphics and gameplay Probably the best space-shooter which is in QB.
10 QMidi v4.1
Ever wanted to play MIDI files in your game? Well this will let you! Get this if you don't use DS4QB.

Category: Comments: Score:
Site URL: (QB Talk) N/A
Graphics: There aren't many graphics, and the ones which're there aren't that good.... 3/10
Content: Rants, rambles, comics and mini games! I like coming to this site just to read something interesting. The webmaster has written a bunch of rants on different subjects. Check them all out (if you have time to read 'em all). 19/20
Layout: The layout isn't to special. Just a few tables with text in 'em. Although the site is easy to navigate so that puts it up. 7/10
Downloads: Not the main focus of the site but the download which are there are interesting to say the least. 4/5
Overall Score: 33/45


And finally here's part two of the XMS tutorial!!! I say finally because I originally submitted the first article to the QB Times, then they stopped making new issues. =( Anyways it's finally here and now we'll finish this small series off.

Last issue we covered the bare essentials of XMS. From those routines presented you can make other routines to do just about anything with XMS. One thing I've done with XMS is make a routine to read a map which I've saved in it. All I have to pass to the routine is the x and y position I want to read and the function returns the tile number at that offset. Another thing to use it for is to store graphics. No, not off screen buffers but the PUT/GET compatible arrays. This alone will save you loads of memory depending on your program. There are lots of uses for XMS, I'll leave you to discover your own. So lets get started.

What I didn't show you how to do last month was to use above 64MB of memory. Well now I will show you how to do that in a few of the functions from last month. To do this we need to use the Super Extended Memory support functions. These will make use of 32-bit registers. The funtions we'll be changing are XMSInfo, XMSAlloc, and XMSReAlloc, from last month. You might have thought that XMSPut and XMSGet needed to be changed as well, but no. So the best place to start is with XMSInfo. We'll change it to return long-integer values about the free memory.

XMSInfo PROC freemem:DWORD, totalmem:DWORD
 mov ah,88h                         ;Use function 88h
 call [XMSControl]                  ;Call the API
 mov bx,totalmem                    ;Put the value in EDX in totalmem.
 mov [bx],edx 
 mov bx,freemem                     ;Put the value of EAX in freemem
 mov [bx],eax

This will return values of up to 4GB in size (all in KB). What we did was use EAX, and EDX and change function 08h to 88h.

Now lets change XMSAllocate routine. This is also really simple:

 mov ah,89h                         ;Use function 89h
 mov edx,kb                         ;Move kb into EDX.
 call [XMSControl]                  ;Call the API
 cmp ax,0001h                       ;Is AX = 0001h? If it is then it worked!
 jne AllocErr                       ;If it isn't then . . . too bad! =P
 mov ax,dx                          ;Move the handle into AX so its returned.
AllocErr:                           ;Since we can't get a handle if it didn't work we don't
 ret                                ;want DX to get into AX.

What we did there was change 09h to 89h and change DX to EDX since we want a 32-bit value for our handle size. Really for all the functions we're changing only the size of the registers and the function numbers.

Now lets change the XMSReAllocate function around:

XMSReAlloc proc handle:WORD, kb:DWORD
 mov ah,8Fh                        ;Use subfunction 8Fh
 mov bx,handle                     ;Get the handle to deallocate into DX.
 mov dx,[bx]
 mov ebx,kb                        ;Get the new amount to resize the handle to into EBX.
 call [XMSControl]                 ;Call the API.
 mov bx,handle                     ;Return the handle to QB.
 mov [bx],ax
endp XMSReAlloc

And there we go! That's it. Now you can allocate and use up to 4GB of memory. Now to use this lib you should put all the functions in one .ASM file and assemble it using an assembler (I used TASM to do the above functions). Then you should link the .OBJ file into a library. I'm not going to explain in detail how to do this, there are other utilities, and tutorials to do that. The include file you need should look something like this:


DECLARE SUB XMSInfo (free&, total&)
DECLARE SUB XMSDeAlloc (handle%)
DECLARE SUB XMSReAlloc (handle%, BYVAL kb&)
DECLARE FUNCTION Move2XMS% (BYVAL handle%, BYVAL segm%, BYVAL offs%, BYVAL bytes&, BYVAL XMSoffs&)
DECLARE FUNCTION Move2Var% (BYVAL handle%, BYVAL segm%, BYVAL offs%, BYVAL bytes&, BYVAL XMSoffs&)

And there you go! XMS fo QB!! If you still don't understand this then you might want to contact me then I can (hopefully) explain it to you. If you find any mistakes for this then also please contact me. I just hate having error's in my tutorials. =) Hope you enjoyed!

This article was written by: Fling-master -

Welcome to part two of my series! Last issue we went over how to create the basic engine, which of course, included such things as movement, collision detectiom, and drawing the map. This time we'll delve deeper into the world of NPCs. We'll create the beginnings of an object system, that will allow us to incorporate enemies with very small modification. And it will allow us to make the player shoot with also very small modification. So before I get too ahead of myself, let's begin!

Before we start coding the object handler to move our NPCs we need to plan out the data structure to hold the required information. What will we need to include in this? Well, you should definitly include things like the NPCs x and y position, the direction its moving, and how much distance it has left to move before it should start moving again. Another thing which'll come in handy later is whether it's active or not. This allows us to 'kill' NPCs. These are just some of the things to include. You might even go so far as to track separate variables to see what items the NPC has so you could trade with them. Something I don't like doing is keeping the text the NPC is going to say in the data structure. This more limits the scripting capabilities of your RPG. But of course we'll get into that later.

So here's out basic data structure:

TYPE NPCType                  'Holds NPC data
 x       AS INTEGER           'X coord
 y       AS INTEGER           'Y coord
 Dir     AS INTEGER           'The direction
 Moving  AS INTEGER           'If its moving and the amount left
 Active  AS INTEGER           'Is it active?

I think that's pretty self-explanatory. Add that into the engine we made last month after the Engine Type declaration.

Now then, we need to write a sub to update the NPCs since we don't want 'em to just stand there! We want them to move, run, etc. We're going to implement a random movement system which will check for collision with walls and other NPCs. This is probably the simplest form of handling NPCs. A more advanced one would maybe make them able to activate scripts or make some run around in circles, etc. Here's the subroutine:

SUB UpdateNPCs
FOR i = 0 TO Engine.MaxNPCs            'Update all the NPCs
 IF NPC(i).Moving = 0 THEN             'Is it moving?
  IF RND * 50 = 5 THEN                 'Find out if it "wants" to move
	NPC(i).Moving = 16             'Set Moving to 16 (one tile width)
	GOTO StartIt		       'Goto the next NPC
  NPC(i).Dir = RND * 4       'Pick a direction
	CASE North                          'Moving north
	 'Do collision. We don't want 'em moving into walls and such =)
	 tile = map(NPC(i).x \ 16, (NPC(i).y - 1) \ 16).Collision
	 tile2 = map((NPC(i).x + 15) \ 16), (NPC(i).y - 1) \ 16).Collision
	 IF tile <> 2 AND tile2 <> 2 THEN	'Is it passible?
	  NPC(i).Moving = 0 'If the tile is unwalkable the NPC stops
	 FOR sw = 0 TO Engine.MaxNPCs   'We also don't want 'em walking onto NPCs
	  IF NPC(i).x \ 16 = NPC(sw).x \ 16 AND (NPC(i).y \ 16) - 1 = NPC(sw).y \ 16 THEN
		NPC(i).Moving = 0	'If there's a NPC stop.
	 NEXT sw
	CASE South                         'Moving South
	 'Do collision. We don't want 'em moving into walls and such =)
	 tile = map(NPC(i).x \ 16, (NPC(i).y + 16) \ 16).Collision
	 tile2 = map((NPC(i).x + 15) \ 16, (NPC(i).y + 16) \ 16).Collision
	 IF tile <> 2 AND tile2 <> 2 THEN	'Is it passible?
	  NPC(i).Moving = 0 'If the tile is unwalkable the NPC stops
	 FOR sw = 0 TO Engine.MaxNPCs   'We also don't want 'em walking onto NPCs
	  IF NPC(i).x \ 16 = NPC(sw).x \ 16 AND (NPC(i).y \ 16) + 1 = NPC(sw).y \ 16 THEN
		NPC(i).Moving = 0	'If there's a NPC stop.
	 NEXT sw
	CASE East                          'Moving East
	 'Do collision. We don't want 'em moving into walls and such =)
	 tile = map((NPC(i).x + 16) \ 16, NPC(i).y \ 16).Collision
	 tile2 = map((NPC(i).x + 16) \ 16, (NPC(i).y + 15) \ 16).Collision
	 IF tile <> 2 AND tile2 <> 2 THEN	'Is it passible?
	  NPC(i).Moving = 0 'If the tile is unwalkable the NPC stops
	 FOR sw = 0 TO Engine.MaxNPCs   'We also don't want 'em walking onto NPCs
	  IF (NPC(i).x \ 16) + 1 = NPC(sw).x \ 16 AND NPC(i).y \ 16 = NPC(sw).y \ 16 THEN
		NPC(i).Moving = 0	'If there's a NPC stop.
	 NEXT sw
	CASE West                          'Moving West
	 'Do collision. We don't want 'em moving into walls and such =)
	 tile = map((NPC(i).x - 1) \ 16, NPC(i).y \ 16).Collision
	 tile2 = map((NPC(i).x - 1) \ 16, (NPC(i).y + 15) \ 16).Collision
	 IF tile <> 2 AND tile2 <> 2 THEN	'Is it passible?
	  NPC(i).Moving = 0 'If the tile is unwalkable the NPC stops
	 FOR sw = 0 TO Engine.MaxNPCs   'We also don't want 'em walking onto NPCs
	  IF (NPC(i).x \ 16) - 1 = NPC(sw).x \ 16 AND NPC(i).y \ 16 = NPC(sw).y \ 16 THEN
		NPC(i).Moving = 0	'If there's a NPC stop.
	 NEXT sw

 'If the NPC is moving then update the current position its at.
 IF NPC(i).Moving > 0 THEN
  NPC(i).Moving = NPC(i).Moving - 1
	CASE North
	 NPC(i).y = NPC(i).y - 1
	CASE South
	 NPC(i).y = NPC(i).y + 1
	CASE East
	 NPC(i).x = NPC(i).x + 1
	CASE West
	 NPC(i).x = NPC(i).x - 1
StartIt:			'This is where we go to goto the next NPC.

Hopefully you understand that! =) What it does is check if the current NPC is moving, if not then find out if it "wants" to move by picking a random number. If it does "want" to then we pick a random direction, check for collision and set it on its way. If the NPC was already moving then we simply find out which way it was heading then we update the x,y position accordingly. Simple? Yes! (Well I hope 'Yes!')

So now we've got out NPC handler, and that's fine, BUT how do we display them? Well that is actually quite simple! The routine to draw the NPC's is really small and the bonus here is that when we add other objects like enemies and items, etc. this routine will draw them too! Excellent! So here's the code:

FOR i = 0 TO Engine.MaxNPCs
 IF NPC(i).Active = False THEN GOTO NextNPC   'Is the NPC Active?
 Xpos = NPC(i).x - CameraX                    'Get the coords to draw the NPC
 Ypos = NPC(i).y - CameraY                    'at on the screen
 NPCpic = (NPC(i).Dir * 2) - 1                'Get the frame the NPC is in
 Put VARSEG(buffer(0)), Xpos, Ypos, PlayerGFX(0, NPCpic)    'Draw it
NextNPC:                                      'Process the next NPC
Xpos = Engine.x - CameraX                     'Now get the player's coords
Ypos = Engine.y - CameraY                     'to draw
PlayerPic = ((Engine.Direction * 2) - 1)      'Get frame
Put VARSEG(buffer(0)), Xpos, Ypos, PlayerGFX(0, PlayerPic)  'Draw it

There we go! That will also draw the player onscreen too so you can get rid of the lines which draw the player in the DrawMap sub from last issue and replace it with a call to this routine. Also note that the player is always drawn on top of everything (which will change when we start paying more attention to layers). This is so that you don't get him being below anything and can always see him. What this routine really needs is animation but I forgot the formula to do that, I'll show you it next issue though ;).

Well that just about covers it. But one last thing is probably on your mind: How do I initialize NPCs so they appear on the map? Well this is simple but I'll still show you how to do it:

NPC(i).x = <where-ever-you-want>
NPC(i).y = <where-ever-you-want>
NPC(i).Dir = South
NPC(i).Active = True

'This is something I forgot to give you last issue. It initializes some of the Engine's required variables.
Engine.x = <where-ever-you-want>    'Our starting position
Engine.y = <where-ever-you-want>
Engine.Direction = South            'We'll face south
Engine.MaxNPCs = 10                 'Maximum NPCs is 5
skip = 1                            'Frame skip

The top four lines will initialize one NPC (you have to substitute your NPCs starting co-ordinates). It also sets it to face south and to be active. Also as you can see we've got 5 extra lines which deal with the Engine data structure. Well these setup some variables required by the engine. The 'skip=1' down at the bottom is the frame skip. You can set it so that when you move the players x,y position decrease/increases by skip. This will later allow us to make the player run if you have a multiple keypress handler (all you'd have to do is make skip=2 or something when the player holds the run key down). A word of warning: don't set skip to an odd number. If you do you will eventually skip tiles and mess the collision detection up. Always make it either 2,4,8 or 16.

And that cover's everything I wanted to say about NPCs for this issue. Next month we'll go into scripting because I'm not quite ready for explaining my battle system yet. We'll also give those NPCs something to say! See you next month!

This article was written by: Fling-master -

It is a well known fact that a large percentage of QB projects flop. In other words, most QB projects are never completed before the creator or creators of the project abandon this project or worse, quit QB programming altogether. I know of many good examples, the most recent major abandonment being the "QPower" project by Nekrophidus. I have abandoned many of my programs in the past, most notable the text side-scrolling platform game called The Heart Machine. If you have no idea what I am referring to, check out this engine at the programs I have done so far at my website QBTalk. I'm hoping someone will continue with this, but let us not digress any further. The topic for today is: why doesn't everyone finish their QB projects, even those which people have spent many hours planning every single detail?

Let me start on my own experience. The main reason for abandoning My Heart Machine, which looked impressive enough (quote: "CS" on the Future Software board - "It's the coolest thing I've ever seen!") as a platform engine is the horrors of stale code. I repeat this point: the horrors of stale code. Code you've written when you're half drunk. Code you've written on a sudden flash of inspiration. Code you've never dreamt that you have the capability to write. Code that will sting, code that will stun. Code that makes you forget what it means 10 minutes after creating it. Code that makes you say, "How did I do that?". Code that makes you say, "What exactly does it mean?" even with the comments on it. Yup, I think you've got it. You write some brilliant piece of code, and when you realize some days later that you have to change some portions of this code to put in something new, you find out that, in spite of your comments (not that there were many comments in The Heart Machine anyway), you forgot what your code means. To understanding chunks and chucks of stale code is a horror. The horrification level can only be matched by the "power-bugs" mentioned below. Usually, what I would do is to persevere, but the code for The Heart Machine is really too lethal to be touched by me. I wish any more experienced programmer who fiddles with it good luck (then again, experienced programmers would be able to write something better than that with the boost of ASM)

The next most important reason why I gave up The Heart Machine is the level of tedious programming I did not expect. All was well when I programmed the side scrolling effect, implemented multiples walls and floors, water and clouds, and even when implemented 3 different kinds of shooting (I thought I would have a problem here). The only problem remains: what about monsters to shoot at? I wrote down an extensive planning process, about the coordinates of the monsters, how the monsters will behave (monster AI), whether monster will shoot or not, and what they look like on the screen, and whether they will slow the whole game down drastically. Plans after plans of implementing monsters are drawn and scrapped, and after planning this for one whole week without any result in getting rid of the obvious speed problems, and I found out that nothing would be achieved even if I continue this way. Furthermore, there were bosses to think about. All these pile together and they require extremely long periods of programming and tweaking. I cannot imagine the debugging process of this. That's why I gave up The Heart Machine. Very large projects should not be done by one or two people alone, as they are most likely to fall prey on the tedious programming obstacle.

That was two reasons using myself as a case study. There are quite a few more rather major obstacles to completing a project. If you trip upon these obstacles, you may not be able to finish your QB project. One of the most serious problem is the "power-bugs" problem, which can also be called the "brick-wall syndrome".

"Power bugs" refer to those bugs that just wouldn't go away no matter how you try to extract the bug. Examining the code in every corner would not work; neither does stepping through the program and watching all your variables at every instant. When you step to the line where it errors, you just cannot find out why the program screw up. The worse case of "power bugs" is the case where you cannot even run your program. "Out of string space", "Out of data space", "Out of stack space" all these are potentially mean "power bugs" that occur when you start. Worth mentioning is the "Do without loop" bugs, as they could mean that your control statements (IF and SELECT CASE) are not closed. Other than these cases, "Subscript out of range" is a very irritating "power bug", especially you have some complex formulae for the subscripts of your array. In that case, you have to watch all your variables carefully, and see which are the ones that are getting the wrong manipulation. This problem is also called the "brick-wall syndrome" because it is said that since you cannot continue programming the project until after you vanquish the bug, you get your face smashed against a brick wall, and there is no way to continue. Power bugs are horrific. Take note of this.

Sometimes though, it is not the case of power bugs. For some programmers, especially newbies, they will find that the biggest obstacle to completing programs is the lack of programming capability and experience. This is another major problem that arrives especially you you did not do adequate planning when you begin your programs. Most less experienced programmers nose- dive into the programming portion of the project without even planning how your code should be structured, what tools and algorithms you need, and what data you need to create. This is a serious error. At the risk of sounding like an old nag, I have to say planning of a program, even if it is just a rough sketch, is important. At most, it acts as a valuable guide to programming and can certainly reduce the debugging time by reducing the possibility of "power bugs" and other less serious one. At the very least, it helps you gain confidence that you know roughly how to do the program or let you realize that you don't know enough to write such a program and let you bail out before actually starting on the programming. Less experienced programmers generally have less experience with debugging, so, when met with a bug that appears to be a "power bug" to them, they will bail out, thus turning the program into a flop. Therefore, the lack of experience and programming capability is a major hindrance of completing a QB project.

We cannot forget the fact that QB programmers have a social life too (well, at least most of them do...). Due to some additional commitments in their school / work life, the expanding of the social circle as well as maybe some family matters, some QB programmers find that it is impossible to juggle social life and programming projects together. Thus, they choose to give up the less important one: programming projects. Some hardcore programmers think that their social life is less important  and consequently, gave that up. These are what we can truly call the "geeks". Anyway, QB programmers may not be able to finish their project because of this. They are not really to be blamed.

All in all, many QB programmers don't finish their QB projects. It's a fact, and we should live with it. Maybe one day, you will look back at some of your projects and decide to continue it. So whatever you do, don't ever delete the source files of your abandoned projects away. Save them in a backup disk, put them somewhere else, whatever you do, don't just trash it. You might want to continue.

This article was written by: Singsong -


Ahh yes the palette. Your best friend when making a game. Well, it can be anyway. The palette in SCREEN 13 can be quite important, mostly because the default one is really quite crap unless you're adventurous. So your first order of business should be to change it around to what you want.

Most people find that when making a palette it helps to use gradients. A gradient is of course a series of colours which go from either a dark shade to a light or vice-versa. Anyway, how does one change the palette? Well I'm here to answer that question and some. =)

The first thing we'll cover is changing the RGB values for colours. RGB stands for red, green, blue. If you don't already know every colour on your screen is made up of different values of red green and blue. By mixing different amounts of these three colours you can get basically any colour you want. Now I'm not going to go over "rules" for palette creation, that's for another article. So anyway, we can change the value by first OUTing to port 3C8h the colour we want to change. Then we OUT to 3C9h the red, green, and blue values of the new colour. An example:

SCREEN 13			'We'll use mode 13h for this
COLOR 1				'Colour blue for the text
OUT &H3C8, 0			'Let's change the background colour
OUT &H3C9, 63			'Change the red value
OUT &H3C9, 63			'...and the green
OUT &H3C9, 63			'...and the blue
PRINT "Colour 0 is now white!"

In case you didn't read the last line, this example changes colour zero to white. Colour zero is the background colour so you'll notice something different. =) Now, white is made up of 63 for R, G and B. Black is 0 for R, G and B. Bright green would be R=0, G=63, and B=0. I think now you understand.

OK so what if you wanted to get the RGB values of a certain colour? Just what do you do? Well first you OUT the colour whoes values you want to read to port 3C7h. Then you INP from port 3C9h the red, green, then blue values. Simple? Yes I thought so too. Here's an example:

OUT &H3C7, 100			'Get the colours for colour 100
r = INP(&H3C9)  		'Get the red value
g = INP(&H3C9)  		'... and the green
b = INP(&H3C9)  		'... and the blue
PRINT "Red:", r 		'Now show the values of that colour
PRINT "Green:", g
PRINT "Blue:", b

That will display, on screen, the RGB values of colour 100. So what can we do with this knowledge? Well we can do interesting stuff like fades. Or we could make a fully featured palette editor. I think the best example is something which modifies the palette in some way. So lets make a fading routine. This will work in SCREEN 13. Here's the commented code:

change = 50               'We're gonna darken the palette by 50 shades
FOR c = 0 TO 255          'Go thru all the colours
 OUT &H3C7, c
 r = INP(&H3C9)           'Get the red value
 g = INP(&H3C9)           'green
 b = INP(&H3C9)           'blue
 FOR i = 1 TO change      'Loop through as many times as shades we want to darken
  IF r > 0 THEN r = r - 1 'If any of the RGB values is below 0 we don't
  IF g > 0 THEN g = g - 1 'want to change 'em.
  IF b > 0 THEN b = b - 1
  OUT &H3C8, c            'Now we want to make the changes to the palette
  OUT &H3C9, r
  OUT &H3C9, g
  OUT &H3C9, b
NEXT                      'Goto the next colour in the palette.

This doesn't fade the screen smoothly. It just does an 'instant fade' sorta thing. To make it more smooth you should do some timing in one of the loops (not sure which one.... it's late, give me some credit =). You could also make this routine work with textmode. All you gotta do is change the FOR c = 0 TO 255 to FOR c = 0 TO 15 (for 16-colour modes).

Another neat thing you can do is translucencies. When used properly in games, etc, you can get many "Ooooooh"'s and "Aaaaahhh"'s from the users =). We aren't going do something like "alpha-blending". We are going do something which is both memory efficient and speedy. Our translucent pixel routine will make use of an array with 256 integers in it. Here's the code:

DIM SHARED TransData(256)           'Our translucency data

SCREEN 13                           'Use mode 13h

'Here we're gonna initialize the translucent data. You only need to do this
'once at the starting of your program.
FOR i = 0 TO 255                    'Go thru all the colours
 done = 0                           'A tracker variable to see if we've
                                    'done something this time thru the loop
 OUT &H3C7, i                       'Get the RGB values for the current
 r = INP(&H3C9)                     'colour
 g = INP(&H3C9)
 b = INP(&H3C9)

 'Now we want to find the highest of the RGB values and add 'em to the array
 'At the end of the loop our translucency data array will be filled with
 'numbers from 0-15.
 IF r >= b AND r >= g THEN          'Is red highest?
  TransData(i) = r / 4
  done = 1
 IF b >= g AND done <> 1 THEN       'Is blue highest?
  TransData(i) = b / 4
  done = 1
 IF done <> 1 THEN TransData(i) = g / 4 'Is green highest?

'Here "colr" is the colour of the pixel which we're plotting the translucent
'pixel over. Then what we want to do is find out where the gradient of the
'shade we want to put starts and use that colour.
DEF SEG = &HA000
colr = POINT(x, y)
POKE y * 320& + x, TransData(colr) + start_of_desired_shade

The above routine would be much speedier in asm. That is the simplest form of translucency, and is also the fastest that I know of. Something like alpha blending works best in 16-bit and above colour modes. You technically can use alpha blending in 256 colour modes but its not worth it especially when you can do the above.

Anyway thats my article on the palette in QB. Hope you enjoyed it. If you don't understand something then please e-mail me. If you see an error e-mail me too!

This article was written by: Fling-master -

Well thanks for reading this issue! I hope you enjoyed this collection of tutorials, news, and rants. The next issue is due to be out around April 7th. In it we'll have part 3 of the RPG Creation 101 series. We'll also most likely have an article on using EMS. And we'll have another rant for your reading pleasure.

Until next time!

All site content is Copyright 2001, HyperRealistic Games. This excludes content submitted by other people.