Fun With QBasic?!?!?!

Believe it, or not, these last couple of days, I’ve actually been having fun with QBasic.

Of course, this has all been a big distraction to my robotics.
:frowning:

Until now, all I’ve used it for is number crunching.

But, it turns out that there’s a lot more that one can do with it.

I’ve been making a game that will eventually be a low-graphics version of Worms/Gunbound (3rd person free-for-all shooters).

Right now, it’s in it’s baby stages.

Here’s what I’ve got so far.

Feel free to play around with the game or the code.

To play the game, follow these steps:

  1. Download an about 1992 version of QBasic (newer ones will probably work, too) for free.
  2. Copy the below code.
  3. Paste it into Notepad.
  4. Click Save As.
  5. Select “all types”
  6. Type in “CANNON.BAS”
  7. Click save.
  8. Go to the folder that you saved it in.
  9. Right click on it.
  10. Select Open With
  11. Click Browse
  12. Find your downloaded “QBasic.exe”
  13. Open it with that.
  14. When you see the code in an MS-DOS window, press F5.

i = more power
k = less power
j = more angle
l = less angle
spacebar = fire
q = quit

I’ve got the physics running well, now.
There’s still a couple formulas that I’ll need to add in, later, when I add in wind velocity and direction.
I’ll also have to add in weapon mass when I give the game more weapons.

Right now, I’m stuck trying to identify when I actually hit the green target.
I’m going to crack open my book, again, and learn how to read the screen pixels as an array, tommorrow.
That would be a slower way to determine hit or miss, but the “faster” way isn’t working for me.

If anyone sees why it isn’t, I’m all ears.

Here’s the code:

CANNON v.1.02 by: Nick Reiser last edited: 4/11/06

'***************************************************************************************
'*****************************SCREEN SETTINGS*******************************************
'***************************************************************************************
''''''''''''''''''''''''''''''Clear the screen.
CLS

''''''''''''''''''''''''''''''Switch to Medium graphics mode.
SCREEN 1
                                            
''''''''''''''''''''''''''''''Sky blue background, green, red, brown pallete.
COLOR 9, 0

''''''''''''''''''''''''''''''Make display screen's coordinates Cartesian.
WINDOW (0, 199)-(319, 0)

''''''''''''''''''''''''''''''Make Cartesian available to DRAW statements.
VIEW (0, 0)-(319, 199)
'***************************************************************************************


'***************************************************************************************
'*****************************DEFAULT GRAPHICS******************************************
'***************************************************************************************
''''''''''''''''''''''''''''''Default power value (m/s).
power = 25

''''''''''''''''''''''''''''''Default cannon angle (in degrees).
theta.deg = 45

''''''''''''''''''''''''''''''Default gravity value (m/s^2).
gravity = 9.81

''''''''''''''''''''''''''''''Default missile tail length.
missile.tail.length = 25

''''''''''''''''''''''''''''''Default game speed.
game.speed# = 1000

''''''''''''''''''''''''''''''Draw cannon at default angle and power.
FOR i = -1 TO 1
        FOR j = -1 TO 1
                PSET (i, j), 3
                DRAW "TA=" + VARPTR$(theta.deg) + "NR=" + VARPTR$(power)
        NEXT j
NEXT i

''''''''''''''''''''''''''''''Randomize first target width
RANDOMIZE TIMER
random.number.width = RND
target.width = INT(random.number.width * 7) + 3

''''''''''''''''''''''''''''''Randomize first target height
RANDOMIZE TIMER
random.number.height = RND
target.height = INT(random.number.height * 5) + 3

''''''''''''''''''''''''''''''Draw first target at random position.
RANDOMIZE TIMER
random.number.position = RND
target.position = INT(random.number.position * 249) + 70
FOR i = (target.width * -1) TO target.width
        FOR j = 0 TO target.height
                PSET (target.position + i, j), 1
        NEXT j
NEXT i
'***************************************************************************************


'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@MAIN PROGRAM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
''''''''''''''''''''''''''''''Create infinite loop.
DO

''''''''''''''''''''''''''''''INKEY$ stores all keys that user presses.
        SELECT CASE INKEY$

'***************************************************************************************
'*****************************UP KEY****************************************************
'***************************************************************************************
''''''''''''''''''''''''''''''When user presses "i" (up) key.
                CASE IS = "i"

''''''''''''''''''''''''''''''Hide the old cannon by coloring it sky blue.
                FOR i = -1 TO 1
                        FOR j = -1 TO 1
''''''''''''''''''''''''''''''PSET gives "NR=" a starting point.
                                PSET (i, j), 0
                                DRAW "TA=" + VARPTR$(theta.deg) + "NR=" + VARPTR$(power)
                        NEXT j
                NEXT i

''''''''''''''''''''''''''''''Add 1 to cannon's length.
                power = power + .5

''''''''''''''''''''''''''''''Restrict cannon from being longer than 60 pixels.
                IF power > 60 THEN
                        power = 60
                END IF

''''''''''''''''''''''''''''''Draw the new, longer cannon.
                FOR i = -1 TO 1
                        FOR j = -1 TO 1
''''''''''''''''''''''''''''''PSET gives "NR=" a starting point.
                                PSET (i, j), 3
                                DRAW "TA=" + VARPTR$(theta.deg) + "NR=" + VARPTR$(power)
                        NEXT j
                NEXT i
'***************************************************************************************

            
'***************************************************************************************
'*****************************DOWN KEY**************************************************
'***************************************************************************************
''''''''''''''''''''''''''''''When user presses "k" (down) key.  
                CASE IS = "k"

''''''''''''''''''''''''''''''Hide the old cannon by coloring it sky blue.
                FOR i = -1 TO 1
                        FOR j = -1 TO 1
''''''''''''''''''''''''''''''PSET gives "NR=" a starting point.
                                PSET (i, j), 0
                                DRAW "TA=" + VARPTR$(theta.deg) + "NR=" + VARPTR$(power)
                        NEXT j
                NEXT i

''''''''''''''''''''''''''''''Subtract 1 from the length of the cannon.
                power = power - .5

''''''''''''''''''''''''''''''Restrict cannon from being shorter than 1 pixel.
                IF power < 1 THEN
                        power = 1
                END IF

''''''''''''''''''''''''''''''Draw the new, shorter cannon.
                FOR i = -1 TO 1
                        FOR j = -1 TO 1
''''''''''''''''''''''''''''''PSET gives "NR=" a starting point.
                                PSET (i, j), 3
                                DRAW "TA=" + VARPTR$(theta.deg) + "NR=" + VARPTR$(power)
                        NEXT j
                NEXT i
'***************************************************************************************


'***************************************************************************************
'*****************************LEFT KEY**************************************************
'***************************************************************************************
''''''''''''''''''''''''''''''When user presses "j" (left) key.
                CASE IS = "j"

''''''''''''''''''''''''''''''Hide old cannon by coloring it sky blue.
                FOR i = -1 TO 1
                        FOR j = -1 TO 1
''''''''''''''''''''''''''''''PSET gives "NR=" a starting point.
                                PSET (i, j), 0
                                DRAW "TA=" + VARPTR$(theta.deg) + "NR=" + VARPTR$(power)
                        NEXT j
                NEXT i

''''''''''''''''''''''''''''''Add half a degree to the cannon's angle.
                theta.deg = theta.deg + .5

''''''''''''''''''''''''''''''Restrict cannon's angle to a 90 degree maximum.
                IF theta.deg > 90 THEN
                        theta.deg = 90
                END IF

''''''''''''''''''''''''''''''Draw cannon at new, higher angle.
                FOR i = -1 TO 1
                        FOR j = -1 TO 1
''''''''''''''''''''''''''''''PSET gives "NR" a starting point.
                                PSET (i, j), 3
                                DRAW "TA=" + VARPTR$(theta.deg) + "NR=" + VARPTR$(power)
                        NEXT j
                NEXT i
'***************************************************************************************


'***************************************************************************************
'*****************************RIGHT KEY*************************************************
'***************************************************************************************
''''''''''''''''''''''''''''''When user presses "l" (right) key.
                CASE IS = "l"

''''''''''''''''''''''''''''''Hide old cannon by coloring it sky blue.
                FOR i = -1 TO 1
                        FOR j = -1 TO 1
''''''''''''''''''''''''''''''PSET gives "NR=" a starting point.
                                PSET (i, j), 0
                                DRAW "TA=" + VARPTR$(theta.deg) + "NR=" + VARPTR$(power)
                        NEXT j
                NEXT i

''''''''''''''''''''''''''''''Subtract half an degree from cannon's angle.
                theta.deg = theta.deg - .5

''''''''''''''''''''''''''''''Restrict cannon's angle to a 0 degree minimum.
                IF theta.deg < 0 THEN
                        theta.deg = 0
                END IF

''''''''''''''''''''''''''''''Draw cannon at new, higher angle.
                FOR i = -1 TO 1
                        FOR j = -1 TO 1
''''''''''''''''''''''''''''''PSET gives "NR=" a starting point.
                                PSET (i, j), 3
                                DRAW "TA=" + VARPTR$(theta.deg) + "NR=" + VARPTR$(power)
                        NEXT j
                NEXT i
'***************************************************************************************


'***************************************************************************************
'*****************************QUIT KEY**************************************************
'***************************************************************************************
''''''''''''''''''''''''''''''When user presses "q" (quit) key.
                CASE IS = "q"

''''''''''''''''''''''''''''''End the program.
                END
'***************************************************************************************    


'***************************************************************************************
'*****************************FIRE KEY**************************************************
'***************************************************************************************
''''''''''''''''''''''''''''''When user presses space bar (fire) key.    
                CASE IS = " "

''''''''''''''''''''''''''''''Hide old impact by coloring it sky blue.
                FOR i = -1 TO 1
                        FOR j = 0 TO 1
                                PSET (impact + i, j), 0
                        NEXT j
                NEXT i

''''''''''''''''''''''''''''''Hide old peak by coloring it sky blue.
                PSET (0, ymax), 0

''''''''''''''''''''''''''''''Change cannon's angle from degrees to radians.
                theta.rad = (theta.deg / 360 * 2 * 3.1415)

''''''''''''''''''''''''''''''Calculate the x coordinate of impact.
                impact = (power ^ 2) / gravity * SIN(2 * theta.rad)

''''''''''''''''''''''''''''''Calculate, plot, and then hide the trajectory.
                FOR x = 0 TO impact
                        FOR delay# = 1 TO game.speed#
                        NEXT delay#
                        PSET (x, y), 2
                        y = x * TAN(theta.rad) - .5 * gravity * (x ^ 2 / ((power ^ 2) * COS(theta.rad) * COS(theta.rad)))
                        PSET (hidex, hidey), 0
                        hidex = x - trajectory.tail.length
                        y = x * TAN(theta.rad) - .5 * gravity * (x ^ 2 / ((power ^ 2) * COS(theta.rad) * COS(theta.rad)))
                NEXT x

''''''''''''''''''''''''''''''Hide old trajectory by coloring it sky blue.
                FOR x = 0 TO impact
                        PSET (x, y), 0
                        y = x * TAN(theta.rad) - .5 * gravity * (x ^ 2 / ((power ^ 2) * COS(theta.rad) * COS(theta.rad)))
                NEXT x

''''''''''''''''''''''''''''''Display the 3 x 2 impact rectangle.
                FOR i = -1 TO 1
                        FOR j = 0 TO 1
                                PSET (impact + i, j), 2
                        NEXT j
                NEXT i

'''''''''''''''''''''''''''''Target hit?
                FOR i = (target.width * -1) TO target.width
'''''''''''''''''''''''''''''Find the value (1 or 2) of a target's pixel.
                        color.point = POINT((target.position + i), 1)
'''''''''''''''''''''''''''''If any of those pixels are red, then trigger.
                        IF color.point = 2 THEN
                                hide.target = 1
                        END IF
                NEXT i

''''''''''''''''''''''''''''''If target hit, then hide the old target.
                IF hide.target = 1 THEN
                        FOR i = (target.width * -1) TO target.width
                                FOR j = 0 TO target.height
                                        PSET ((target.position + i), j), 0
                                NEXT j
                        NEXT i

''''''''''''''''''''''''''''''Randomize new target width
                        RANDOMIZE TIMER
                        random.number.width = RND
                        target.width = INT(random.number.width * 7) + 3

''''''''''''''''''''''''''''''Randomize new target height
                        RANDOMIZE TIMER
                        random.number.height = RND
                        target.height = INT(random.number.height * 5) + 3

''''''''''''''''''''''''''''''Draw new target at random position.
                        RANDOMIZE TIMER
                        random.number.position = RND
                        target.position = INT(random.number.position * 249) + 70
                        FOR i = (target.width * -1) TO target.width
                                FOR j = 0 TO target.height
                                        PSET ((target.position + i), j), 1
                                NEXT j
                        NEXT i

''''''''''''''''''''''''''''''Reset the triggers for future events.
                        hide.target = 0
                END IF
''''''''''''''''''''''''''''''Calculate the peak of the trajectory.
                ymax = power ^ 2 * SIN(theta.rad) * SIN(theta.rad) / (2 * gravity)

''''''''''''''''''''''''''''''Display trajectory peak as a pixel on the left.
                PSET (0, ymax), 3
'***************************************************************************************

               
                END SELECT

LOOP
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Hey Nick,

I tried your program it brought back many memories. Qbasic was so much fun because it was so easy to make you own computer graphics games using it.

I wish I still had a copy of my game F-15E I made back in '96, It featured 256 color graphics, and the player would use a joystick to bank the jet left and right. I had a horizon line that moved in relation to the joystick input. The two exhaust ports of the jet would cycle though 14 colors giving it an after burner flicker effect. The object of the game was to shoot down enemy targets but the challenges was when you moved the joystick to shoot the enemy, the enemy would move away slightly giving the feeling of a dog fight. The enemy object would randomly change directions, so you would have to bank the other direction and struggle to get the target in the HUDs crosshairs.

Yes… the memories…

:smiley:

Sounds like that was a blast.

I’m saving every program that I’ll ever make on flash drives.
I find that I’m continually going back and reusing code, which saves loads of time.

Do you remember how you managed cramming 256 colors into the screen?
I haven’t found a way to get more than 8 colors in medium or high graphics mode (SCREEN 1 & SCREEN 2).

My teacher laughs at me because I always put more comment in than actual code.
It looks nice and pretty, though, doesn’t it?

:laughing:

I cant remember exactly how I did the 256 colors. I used a section of code from another person’s program that allowed me to use 256 color graphics, in fact, I also used a graphics utility that allowed a user to paint 256 color images using a mouse, then when you’re done, you could save the image to be used in you own game using BLOAD.

If I remember right, I used screen 13.

I tied finding his progam on the web to download, but I could only find the arcade game he made called “dimension man”

He went by the name S.H. Soft Worx

The program name was QBpaint or Qbasic paint, I can’t remember.

Thanks, Mike.

^.^

That should be enough to get me to it, or at least to someone who’s heard of it.

You don’t happen to see what’s wrong with the IF THEN statement near the end that’s commented “Check to see if target is hit.”, do you?

I’ve isolated the issue down to that piece of code by putting a PRINT “Working properly.” inside that loop.

I’m not getting any messages, though, so it’s as I thought, not detecting that I’ve shot the little pooper.

Nick, copy/paste this code to see how POINT works. I spent a good hour on it for you. I never did add the quit command, I forgot. You will need to use CTRL+Break to stop the program. :laughing:

'----------------------( POINT DEMO )-----------------------------
    '----------------------( By: Mike B )-----------------------------

    ' the value #4 is RED in screen mode 12.
    ' You can play around with the color value and pont will return
    ' the proper color value. This can be used to detect if an object
    ' was "HIT" by checking a specific color pixel and a specified
    ' location.
    '
    '-----------------------------------------------------------------

    SCREEN 12
    CLS
    ' Draw box to set screen
    LINE (0, 0)-(10, 10), 4, BF
   
    DO
   
    LOCATE 15, 1

    INPUT " Enter value 1-20, Press Q to quit"; x
   
    CLS

   '5,5 is the middle of the red box. 20,20 is out side the red box
   
    y = 5
   
    ' change the value 4 to any number between 1 and 15
   
    LINE (0, 0)-(10, 10), 4, BF       ' draw a red box top left of screen
   
    LOCATE 2, 30                      'print results top middle of screen

    PRINT "the value is"; POINT(x, y) 'show color value found
    n = POINT(x, y)                   'set n to color value of POINT
    PSET (x, 5)                       'draw a dot to show where POINT is pointing
    IF n < 1 THEN
    
    'IF value = 0 THEN PRINT "miss"

        LOCATE 3, 30
        PRINT "Target missed!     "
                ELSE
                LOCATE 3, 30
                PRINT "Target HIT!     "
    END IF
    
LOOP

Sweet.

:smiley:

Thanks, Mike.

^.^

This is exactly what I needed.
POINT seems to be much more straight-foreward (and, thus, reliable) than relying on my physics engine (hate physics, blegh!).

Definitely an hour well-spent, hehe.
And, now I can stop staring at my broken code and simply rewrite it differently (which is probably going to save time, at this point).
I’ll edit the posted code, as soon as I’ve gotten it fixed.

Btw, why use SCREEN 12?

I haven’t found a decent description of anything but 0, 1, and 2.
It seems that most people don’t use the others.

Do you know of a site that describes all of the screens?

I used screen 12 just to demo the POINT command. Other screen modes only support cetrain colors.

if you go to Qbasic HELP, you can read about the different screen modes there.

Doh, that was dumb.
:stuck_out_tongue:

Anyhow, I found out that screens 13 (and 12 and 14, too, I believe) allow 256 colors.

So, no program needed ^.^

I edited the code, above, and I now have the basics working (no pun intended).

My next project is to invent some fun weapons.
Scatter-shot will be the first that I attempt to conquer.

Now that I’m done with that QBasic class (ugh!), I’m focusing on learning Visual Basic Express better.

And the only way to do that…
Is to have fun.
:smiley:

So, I made a funny program wherein I frustrate the user.
First, there’s a button, that says “CLICK ME” in the middle of the screen.
But, the user can’t click it, because the mouse jumps over the button when it nears it.
Then, when the user tries to hit the close button, it runs away from their mouse, as do the minimize and maximize buttons.
Meanwhile, the happy face icon on the program’s title bar pops up with speach bubbles and insults the user when the user can’t manage to do things.
And, to top it all off, when the user tries to click the area around the program’s window (it’s a small window), nothing happens.
The displayed background, startmenu, and all is just a screenshot of the background before the program was loaded.

It was really funny when I was making it, because I’d find myself falling for my own tricks.
:laughing:

My new project is a revamp of the above game (in Visual Basic Express, this time).
I never got to the point where I’d actually have the computer players do anything, so I’m interested in how I’m going to figure that out.

There’s a lot of things that are nice about VBE, but there’s a lot that’s completely lacking.

For one… there’s no function to determine the color of a given point.
Nor is there a function to determine if a point is within a polygon… although I’ve heard rumors of samples on the web.
The only ones I’ve found for the polygon thing was a very verbose C++ one.
:angry:

I did manage to get a function for determining a point’s color from a friend who made it.

Has anyone seen any good example code for point-in-polygon determination?

Oh, if anyone wants to see either of these programs, send me an email, and I’ll send them.
I can’t find a place to upload executables.
:angry:

You should really submit the obnoxious interface app to adobe for a interview piece, I hear they are into that kind of stuff :slight_smile:

Point in poly: They have to draw the line somewhere… the framework is already obscenely large and adding things like this only make it so that people who want to run HelloDatabase need to install an even larger framework. So… PointInPoly is easily done as a series of PointInTriangle() calls which I think you’ll find much more managable.

For the pixel data: Assuming you’ve got an Image object, you can create a Bitmap object from it, using the Bitmap(Image) constructor. Bitmap has a method:
Color Bitmap.GetPixel(int x, int y)