Thanks for the compliments =) But I would like to point out abionnnn wrote the ASM tutorial. So all your credit should go to him. You can find an article about .MOV file on Wotsit I didn't put it in this QB Times because it's really big and in Adobe Acrobat format. You can find an article on .ZIP files in this issue though...
To the one who scrolls: READ by B-Czar
I know everything about you. I have connections you cannot imagine. I remain calm and clear-headed most of the time, but you have gone too far. I know you use bellsouth. I know where you live, mr. Baton Rouge, Louisiana. I would post your full adress, but I want to save the satisfaction of your utter demise for myself. You are dealing with forces you cannot image, 188.8.131.52... you shall be stopped, one way or another.
I offer you one last chance to leave this board and NEVER return... if you ever come back... well... I won't be responsible forthe reprecussions. Thank you for your time,B-Czar
Then I found this on the QBForum, MadHatter is talking about B-Czar.
Hmmm...something about this tea party is disgusting.... by Madhatter
That isn't B-Czar because B-Czar left for a month and so forth. He also doesn't sound like him so my disregards are that...uh...well...he doesn't sound like him. What if this isn't his IP? What if this is just an enhancement to a plot that we cannot truly comprehend...or possibly just me. Hmmm...oh well....
Posted on Apr 12 1999, 02:38 AM
Also, here's a listing of some messages...
Read this! you dirty old bum!
SHIT HEAD on Apr 11 Your IP is 184.108.40.206
B-Czar on Apr 11 * Ok
APerson on Apr 11 1. Ass Hole
SHIT HEAD on Apr 11 2. Ass Hole
SHIT HEAD on Apr 11 3. Ass Hole
SHIT HEAD on Apr 11 4. Ass Hole
SHIT HEAD on Apr 11 5. Ass Hole
SHIT HEAD on Apr 11 6. Ass Hole
SHIT HEAD on Apr 11
It seems obvious to me that it wasn't B-Czar that flooded the QB Forum. Please tell me your view on this.
Ok, I know I made a very big mistake last issue. For further explaination please read about it in shorts.
FS has a new member
Stefan Hendriks is the newest member of Future Software. He's working in a C&C clone called Arrakis which is really cool. Other Future Software news is that ZeldaClone has been resumed. New BASIC IDE + Compiler
I recently got an e-mail from a guy telling me that het develloped an BASIC IDE + Compiler. He sent me a big mail with the history of the project and some technical specs. Here's a clip from the mail:
Over the years, I developed a 32-bit BASIC language compiler with IDE and GuiDesigner. The original implementation was for the Motorola 88000 RISC CPU running on UNIX. Over the next 4 years I ported XBasic to WindowsNT, SCO UNIX, Linux. Somewhere along the line I let Motorola 88000 and SCO UNIX implementations fall behind, so today the Windows95/98/NT and Linux implementations are the only two left up-to-date. Well, in-sync is probably a better phrase, since I've not worked on XBasic since shortly after Windows95 came out.
Anyway, I was unfortunate enough to grant XBasic marketing license to some total morons. Their marketing model was "tell nobody and hope the phone rings". I've been busy doing other projects and their license expired 2 or 3 years ago.
For some strange reason it recently started to bother me that nobody was getting anything out of "all that work". So I decided to make XBasic available to everyone as freeware, and posted it on my web-site. An overview: http://www.maxreason.com/software/xbasic/xbasic.html (...)
The XBasic programming language is not identical to QBasic or QuickBasic, but its vastly closer than VB. I wrote the original stripped-down XBasic compiler in QuickBasic, then tweaked it into XBasic when the XBasic compiler worked. From then on, all development has been in XBasic. All of XBasic, including its IDE and GuiDesigner is written in XBasic, except a little assembly language for speed critical routines like memory allocation and such.
Way back at the beginning of this project I wrote a QuickBasic to XBasic translator in XBasic. Though I can't find it (?maybe on an 8" floppy?), it is not super difficult to write one again - and maybe even integrate it into the IDE so people could load QBasic programs and run-city. In fact, I just started working on it again and we have some work starting up at the news:alt.lang.basic.compiler newsgroup.
For more information about XBasic you should go to: http://www.maxreason.com/software/xbasic/
Future Software moves to QB45.COM
Last month we told you that Future Software bought QB45.COM and now they actually moved to QB45.COM! Nightwolf Productions has made a deal with Future Software that they get 100MB space at their domain for a little donation.
Future Software also openend a forward service, webmaster can get an address at QB45.COM (http://www.qb45.com/yourname) and a little page which shows an advertisement and your banner or so. Goto http://www.qb45.com/ for more information!
Masamune_q changes nickname to Maz
Somewhere this month Masamune_q mailed everyone in his contact list of ICQ that he was changing his nickname from Masamune_q to Maz.
Nekrophidius joins QB Times crew
Last week I asked Nekrophidius if he wanted to write an article for the QB Times. I told him since he's great at BWSB if he could do a series about BWSB, he agreed and in this issue is his first article! In the next issues he'll continue his articles!
Qlympics finals are over!
All the winners in the Qlympics have been announced. The final scores are below in the table. I congratulate all winners with their prizes!
1st 6.61 Atechos by Steven Crocker
2nd 5.56 Windowz by Jeremy Hammond
3rd 4.67 WinQB 2 by Mr. Cheat Code
4th 4.28 Fake DOS by Chet Zema
5th 3.17 JWH OS by Jonathan Hunt
6th 3.11 QDOS by Ersin Y. Akinci
1st 8.13 SB's Bricks by Eric Schneider
2nd 7.19 TF Tetris by Tom Ford
3rd 6.69 Tetris 2 by Jorden Chamid
4th 5.94 Commander Pang by Thomas Laguzzi
5th 5.75 Grenade Pong by Aaron Sutherlin
6th 5.13 Bombi World by Andrew Gorny
7th 5.06 Renegade Force by Ivan Matyunin
8th 5 Major Inferno 2 by Jeremy Hammond
9th 4.88 Bouncy by Johnny Kauffman
10th 4.69 QB Tron by Mike Hoge
10th 4.69 Tetris by Markus Krütli
12th 4.5 Brawl by Andrew Gorny
13th 4.31 Space Surrender by Ray Hidayat
14th 4.06 Space Explorer by Johan Gustafsson
15th 4 Fight!2 by JiM
16th 3.81 Air by Devin Garner
16th 3.81 Escape from Hell by Jeremy Hammond
1st 7.79 Wetspot 2 by Angelo Mottola
2nd 6.68 Peanut Patrol by Nick London
3rd 6.54 SpaceWar by Bill McDonald
4th 5.86 Stick Fighters 2 by Kevin Reems
5th 5.5 Mario by Danny Gump
6th 5.46 Dudes w/ Attitude by Wafn
7th 5.11 Spaced by Noah Daleo
8th 4.79 EMan by Nathan Horne
9th 4.54 Monster Slayer by Noah Daleo
10th 4.43 Jungle Warrior by Jeremy Moore
1st 6.67 Dark Ages by Michael Hoopmann
2nd 5.81 Mystical by Danny Gump
3rd 5.52 Warrior of the ChiChi by Majiko
4th 4.57 Of Hell and Magic by Aaron Bishop
4th 4.57 QB Game by Ryan Florin
6th 4.52 Lost 1 by Felix Casavahn
7th 4.24 Gimp Warrior by Richard Jacobi and Dan Weber
1st 7.33 TF Checkers by Tom Ford
2nd 6.33 Minesweeper by George Gardiner
2nd 6.33 Puz by Jason Gould
4th 5.67 Mirror Time 2 by Jonty Lovell
5th 5.11 Password by Sunset Rider
6th 4.89 Age of War by Timothy Baldridge and Daniel Rentas
6th 4.89 Othello by Jason Sorensen
6th 4.89 Tic Tac Toe 3D by Richie
9th 4.67 Master Mind by Cheng-Ning Pu
10th 4.33 QGolf by Richie
11th 4 Chinese Squares by Cheng-Ning Pu
12th 3.78 Hangman by Guardian Bob
1st 5.73 Guess Phrase by Guardian Bob
2nd 5.55 AGS by Grant Shreve
3rd 5.27 Drugs Baron by ADeo
4th 5 Stock Market Shark by Damon Amyx
5th 4.91 Battle Tank by Jimmy Griffith
6th 4.55 Hover Wars by Zach Perkins
7th 4.45 Star Wars 20 by Danny Gump
8th 4.09 IRC Chat by Steven Crocker
9th 4 Agent007 by Jimmy Griffith
9th 4 Dark Wizard II by Neal Franzen
9th 4 Dark Wizard III by Neal Franzen
12th 3.91 Dark Wizard by Neal Franzen
13th 3.45 Gem Thief by Jordan Miller
14th 2.27 Magic 8 Ball by Jimmy Griffith
1st 9 PB3D by Marko Dokic
2nd 8 2DBump by Thomas Ludwig
3rd 7.56 PB2DBump by Marko Dokic
4th 7.44 PB2DWater by Marko Dokic
5th 6.78 3D Particles by Thomas Ludwig
6th 6.67 Ripple 2 by Danny Gump
7th 6.22 3D Starfield by Anthony Stamboulis
8th 5.78 Fire Fly by Thomas Ludwig
8th 5.78 Water 2 by hydroXide
10th 5.67 Ripple by Danny Gump
10th 5.67 Thires by Thomas Ludwig
12th 5.44 Water by Thomas Ludwig
13th 5.33 Keko! by Steven Crocker
14th 5.22 Goggles by Viktor Rootselainen
14th 5.22 XMas by Viktor Rootselainen
16th 5.11 Raycaster 1.1 by Mike Hoge
16th 5.11 VS Plasma by Danny Gump
18th 4.89 Digital Clock by Viktor Rootselainen
19th 4.67 B & W Thing by Damon Amyx
19th 4.67 Uninstall by Viktor Rootselainen
19th 4.67 Wars Trek by Danny Gump
22nd 4.22 Ultra Scroll by Peder Johnson
23rd 3.67 Physics by David Nielson
1st 6.29 GIF Converter by QBasic God
2nd 5.86 FontPro by AccuPixel Software
3rd 5.14 VFont2 by Sam Thursfield
4th 5 Open BMP v0.3 by Yousuf Philips
4th 5 Open PCX v0.3 by Yousuf Philips
6th 4.86 MakeFont by Jeremy Hammond
7th 4.71 Open AVI v0.3 by Yousuf Philips
8th 4.4 3Buttons Creations by Jeremy Hammond
9th 4 24bit BMPLoad by Yousuf Philips
1st 6.6 RPGDK2 by Exodus
2nd 6.27 3D Plus by David Nielson
3rd 6.13 Future Library by Jorden Chamid
4th 5.8 Palpitat by Wafn
5th 5.47 ASCII Kit by Sam Lee
6th 4.270 Put by Jeremy Hammond
1st 7.42 JPost by Fred Buffington
2nd 7.33 Install by Fred Buffington
3rd 6.08 Encryption by Mike Conley
4th 5.08 DWA Level Editor by Wafn
5th 4.25 Stack by Thomas Laguzzi
5th 4.25 Ultra-Tools by Jeremy Hammond
7th 4 Electronic Secretary by Cheng-Ning Pu
8th 3.83 JW Basic 2 by Jonathan Hunt
8th 3.83 PhoneBook by Bryan Perfetto
10th 3.67 QB Translator by Mark Andryk
11th 3.5 F1 Manager by Christian Waldschmidt
12th 3.08 Fosil & Librarian by Jonathan Hunt
1st 6.29 SpritedM by Nick Brownfield
2nd 6.14 Sprite Shop by Jason Gould
3rd 6.07 AR Paint by Steven Crocker
4th 5.71 TFR Paint by Steven Crocker
5th 4.64 Draw II by Jack
6th 3.5 DBPaint by Dwaipayan Banerjee
More info: http://majiko.logiclrd.cx/
First of all: Wrath of Sona. Project includes Dave Perry, Linda Willson, Zack Friedrich, and Jason Gould. Last update was May 6th 1999. New featires to be added to the game soon include true dual-layer scrolling highly optimized engine, and more of the REAL storyline...
Second of all:Killers. Being developed by Dave Perry, Linda Willson, and DarkDread. Heavy-memory fighting game with HUGE character sprites, made possible thru DirectQB. No demos have been released yet. Biggest features: bloody graphic violence, wicked high speed, real-time camera zoom, and kewlish special FX.
Thirdly:Kalderan. Being developed by the Bizzare Creations team at www.bizzarecreations.com. SVGA RPG with unparallelled speed and features. Digital music, nice graphics, excellent control. I personally am developing the great battle engine for this game. A couple of demos have been released, the last just a week or so ago.
Fourthly and finally:Furball And Spike. Being developed by Linda Willson, Dave Perry, and Jason Gould. Action/platform game similar in nature to Bubsy. No demos have been released yet, and not many details of the project will be released for quite some time.
I think some things that let it down are the flickering due to lack of buffering (I can only assume that that is the problem). The scrolling is at the time of writing tile based movement which is rather too easy in this day and age. The story is as solid as theoriginal Gameboy version albiet not finished being written and the NPC's of which there are many all have scripted moving and talking. Multiple NPC's can do scripted at the same time. Unfortunately a bug causes the NPC's to randomly dissappear and always dissappear when youtalk to them.
A very good point is that this program is released as an open-source so anyone can take a look at the source and borrow/steal anything. Why you would want to is beyond me though,it is pretty standard stuff on the whole.
Necrolyte's official statement is as follows:
This game will be complete with Walking/Talking NPC's, Animated Tiles, Animated Character, "scripted" moves around the maps, MapEditor (not released). I think Pokemon Unlimited will be a great demo. It has a VERY fast engine, tho fixed with a lil delay :). It's great, so get it today!Booyah!
I think that sums up more than I could talk about so you know where to find him to talk and give comments as this is a very early release and he needs the support from as many people as possible. One last point, can you leave out SBMIDI as it isn't the most efficient thing in the world!
(Also, I'd like to point out that in no way biased to MAZ-Q's version of Pokemon just because we work together - I always write fair and honest reviews of everything I do)
Unfortunately you need SBMIDI loaded and as there are lots of better alternatives nowadays, I'd rather have had in-built support. You do need SVGA, a mouse, XMS and a Sound Blaster (or compat.) to run this.
No collision detection is implemented (why?) which is one of the easiest things to do and the most essential in my opinion. I do hope that the next version includes this.
The frame rate is 30fps on a 333mhz AMD cpu. which is acceptable. The tiles that are in the game are normal to say the least but the actual character/player is superbly drawn albiet small.
The mouse feature currently consists of a mouse on the screen?! Someone please e-mail me and tell me what it does, it's driving me insane. I was asked on loading, "how many NPC's do you want?". I have entered numerous figures but as yet I have failed to see any appear...e-mail me to tell me where these are hiding too! On larger maps the engine handles well using a pixel by pixel scrolling technique (not pixel by tile for a change) which really gives me hope compared to RPGEngine's tile based movement (see last issue). On smaller maps however (10 by 10), I experience shifting of tiles and some sprites being PUT in wrong places so there still is alot to be done. When the mouse is used, NPC's appear and they make more than 3 tiles, i think this is going to be a nice little RPG especially as it features changes between night and day which gives the game a sense of real-time about it. I am looking forward to a proper Beta. (change the midi's guys...FF7 music is so common (track 1))
I firstly opened up the readme to get the basic plot and controls and so on...It all
looked so promising, well documented and detailed steps to run the game. I finally
reached the bottom of the readme and hit the following copyright agreement - One
which I suspect is made up by them and NOT registered with the corrected registrar. -
4. DO NOT PUBLISH THIS GAME IN ANY FORM. DO NOT GIVE IT TO YOUR FRIENDS.
Here is the first strange copyright rule...WHAT? No programmer in Qbasic worth their salt would tell people not to share games that they make. Are these people deliberately trying to alienate a prospective audience...You know what happens, someone downloads a game and plays it. They tell their friends and they say, ok then give me a copy and show me what's so good...They agree and send it over, they play it and so on until the popularity increases beyond comparison. I would love that to happen to my games.
6. ALL TMB PRODUCTS MAY ONLY BE AVALIBLE FROM THE TMB WWW - PAGE.
Also, like the above this alienates your audience by stopping the flow of publicity. I'd happily let NeoZones to add my programs to Qcity for distro. and so by that I would get a review and a mirror server for my games. 2 for the price of 1 even! Anyway, on to the game...though I wish I had deleted it on first sight to be brutally honest.
The intro makes or breaks the game really, first impressions count I am afraid and if a default Qbasic text print function intro is for you, you'll love it. There is little or no shading of the gfx and they themselves are large and blocky. Once you get into the game and start playing you find out there is NO physics engine at all. constant speed no gravity, friction or anything like a calculation there to my eye.
The background doesn't need to have fancy calculations as in TMB's infinite wisdom they have decided to make the background static in the side scrolling game!?! You honestly look like you are in the sea with a static cloud above...there is no perspective brought into this game at all.
Every sprite, or should I say, block, has a large black outline and the ground and most features have NO shading and undecipherable things stuff in the ground. I think I saw a leaf or something...
The collision detection actually brought me to tears...of laughter...You can move pixel by pixel, all very good, but funnily you can walk down a slope but you cannot walk up a slope as the collision stops it!
The animation is almost non-descript but at least it is there. The character themselves such as the enemy crab, which is actually a decent sprite for this game. Finally, they use the Blast! library but insist that they used NO LIBRARIES. Call me a queer but I still think that Blast! is a library whether it uses Interrupt calls or not. They say it is "A way of doing things" instead...Isn't DirectQB a way of doing things? YOU USED A LIBRARY TMB!
To sum up, I would not have released this game, it is bugged with more emphasis on getting something done that is bad than doing anything good that will take slightly longer. I would not download this as it is a waste of my bandwidth. Please save yourself unless your up for a laugh...
(AUTHOR'S NOTE : This is my own opinion and by no way is it the collective thoughts of the
QB Times team. Though I believe they will agree this game is as I say, I am the one
responsible for these reviews...and I am honest. I don't kiss people's asses.)
TMB productions - http://www2.crosswinds.net/members/~tmb/
Pixel by pixel scrolling, move 1 tile at a time: decent to look at, but still pathetic when considering the freedom that the player has.
Now, probably one of the better engines is that of zelda clones, but only if the are done right. Most people find it hard to make these because of the freedom that the player has to move around the place. But this is one of the most simple things to do!To find out what tile a player is on all you do is use the following(very simple) calcs:-
xtile = INT(playerxpos / tilexsize) ytile = INT(playerypos / tileysize)There! Wasn't that easy, now all you must do is check that in the map buffer and you have collision detection!
What about scrolling you ask...Well I'm getting to that. The scrolling
that we are going to use is not any fancy scrolling routines or anything
like that, our map is going to be redrawn each time.
This will require the use of a lib to do a full screen map as you will see.
First of all we are going to implement a camera, this is really cool as there are lots of things you can do with camera routines, for example, in a cut scene that uses the game engine.
We are going to start with the simplest type of camera and basically keep the player in the center of the screen(until he/she hits the edge of the map) this can be done with the following code:-
cameraX = playerX - 160 cameraY = playerY - 100This assumes that you are using mode 13 or 7 and a full screen map. so now the camera is at a place that will have the player in the center of the screen constantly. But, we want the camera to stop moving when the player hits the edge of the map so we just use some simple if's like so:
IF cameraX < 0 THEN cameraX = 0 IF cameraY < 0 THEN cameraY = 0This accounts for the top and left of the screen, but what about the bottom and the right ? well for this we need two more values..maxmapx and maxmapy..so we can tell where to stop the camera going.
IF cameraX > maxmapx-320 THEN cameraX = maxmapX - 320 IF cameraY > maxmapY-200 THEN cameraY = maxmapY - 200This is now allowing the map to stop scrolling when the player enters the edge of the map and stops us from going outside the map buffer also. 320 and 200 are taken away so that we get the top left hand side of the screen, this is where everything is being redrawn from so that is where we need it.
Now for the drawing of the map.
What we want to do here is calculate the tile where the camera starts(NOTE: the tile not the pixel) then we want to add the value of the distance into the tile that the camera is(in pixels) and then redraw the map from there.
So here is how we find out the x and y tiles that the camera is on: for the ease of it we are going to use 20x20 tiles
xtile = INT(cameraX / 20) ytile = INT(cameraY / 20)Now we know which tile the camera is on and which tile to start reading from the map buffer.
DECLARE SUB PUTTILE(X, Y, TILETOPUT) xtile = INT(cameraX / 20) ytile = INT(cameraY / 20) FOR x = 0 to 16 FOR y = 0 to 10 tile = map(x+xtile,y+ytile) xpos = cameraX MOD 20 ypos = cameraY MOD 20 PUTTILE (x*20) - xpos, (y*20) - ypos, tile NEXT NEXTI know this looks hard but I'll talk you through it:
The sub decloration is just to tell you what the parameters I am using are.
Then I calculate the tiles on which the camera lies
Then I start the x and y loops, this is all simple enough. Notice that by using 20x20 tiles and going from 0 to 16 and 0 to 10 that I'm using 1 extra tile either side of the screen, this is because we are going to need some of each tile to be on the screen at any one time.
I get the number of the tile from the map buffer, this assumes a map array with 2 subscripts. by adding the number of the tile that the camera is lying on to the x and y values when reading the map we are effectivly getting the correct offset in the map buffer according to where the camera is, this allows us to redraw only the part of the map being viewed on the screen.
By using the mod function on the camera values we are getting the offset into the tile that the camera is on. Even if you don't understand this, trust me, it works.
Now for the drawing of the tile. The tile is drawn at x*20, y*20 a standard thing in any map engine. Then we minus the distance that the camera is into the tile so that the map is drawn at the right place.
Next and next completes the loop and we have our map drawn.
So now we have our map engine, we can work out where the player is for collision, the map engine supports not only pixel by pixel movement but zelda style free movement around the screen !
Now for one last thing to make it complete. When ever putting sprites on the screen, such as the player or NPC's us the following code. I shouldn't really have to explain this as it is quite obvious:
xpos = playerX - cameraX Ypos = playerY - cameraYAll it does is keep the player on the actual screen.
Geeze that was alot of writting ! Well I hope to see all of you kick ass map engines now, and no more crappy tile by tile junk, even if it scrolls !!!!!
FIRST...load up QB with QB /L MSE_QB (for 4.5) or QBX /L MSE_PDS (for PDS)
This will load the BWSB library. Now, you can start writing your program. The first three major steps are going to be:
DEFINT A-Z '$INCLUDE: 'BWSB.BI' '$INCLUDE: 'GDMTYPE.BI'BWSB requires integers and those two include files to operate. Failure to follow these first few steps WILL RESULT IN A CRASH AND POSSIBLE LOSS OF DATA.
So, with that done, you'll want to keep the rest simple as well, and the best way of doing that is by following pre-built code. Here are a few declarations you'll want to make somewhere at the start of your module:
TYPE MSEConfigFile SoundCard AS INTEGER BaseIO AS INTEGER IRQ AS INTEGER DMA AS INTEGER SoundQuality AS INTEGER END TYPEThat section makes it easier to load the MSE driver file you choose. BWSB requires a driver file, called a Music and Sound Engine, or MSE for short. A file called MSE.CFG can be used to keep this data. However, this is not needed as you can write your own routines, but for now lets keep it simple.
DIM ModHead AS GDMHeaderModHead is used for the GDM module. It is used internally by BWSB, so no need to go into great detail, just make sure that code is added.
DIM SndDevMSE(6) AS STRINGThis is another part of the easy MSE load.
DIM MSEConfig AS MSEConfigFileThis is yet another part of the easy MSE load. In fact, this makes setting the device settings later SO much easier.
Freemem& = FRE(-1) - 80000 A& = SETMEM(-Freemem&)What this segment does is free up 80K of far heap memory. This is needed for the MSE files, plus the patterns. Don't worry if this doesn't make sense right now, if you need to know what this all means, consult the help file in QB.
SndDevMSE(1) = "GUS" 'Gravis Ultrasound SndDevMSE(2) = "SB1X" 'Sound Blaster 1.xx SndDevMSE(3) = "SB2X" 'Sound Blaster 2.xx SndDevMSE(4) = "SBPRO" 'Sound Blaster Pro SndDevMSE(5) = "SB16" 'Sound Blaster 16 SndDevMSE(6) = "PAS" 'Pro AudioSpectrum 16The six MSE files, this part is also part of the easy load.
OPEN "MSE.CFG" FOR BINARY AS 1 GET 1, , MSEConfig CLOSE 1In this last segment, the MSE.CFG file is opened and read. From here on in, its smooth sailing!
IF MSEConfig.SoundCard = 0 THEN PRINT "No Sound Selected in SETUP. Please run SETUP." END END IFIf a soundcard has not been specified, obviously sound will not be available!
MSE$ = SndDevMSE(MSEConfig.SoundCard) + ".MSE"Easy loading stuff again...
SELECT CASE MSEConfig.SoundQuality CASE 0: Ov = 16 CASE 1: Ov = 22 CASE 2: Ov = 45 CASE 3: Ov = 8 END SELECTMSEConfig.SoundQuality sets the variable Ov, which is the Oversampling rate at which sound plays. The higher the oversampling, the better sounding the music, but in most cases, the more processor time taken. The exception to this rule is the presence of a GUS card with 1MB or more of DRAM.
ErrorFlag = LoadMSE(MSE$, 0, Ov, 4096, MSEConfig.BaseIO, MSEConfig.IRQ, MSEConfig.DMA)This last fragment is all it takes to load the MSE. Also, it handles any errors that could occur, and many are possible!
SELECT CASE ErrorFlag CASE 0 CASE 1: PRINT "Base I/O address autodetection failure": END CASE 2: PRINT "IRQ level autodetection failure": END CASE 3: PRINT "DMA channel autodetection failure": END CASE 4: PRINT "DMA channel not supported": END CASE 6: PRINT "Sound device does not respond": END CASE 7: PRINT "Memory control blocks destroyed": END CASE 8: PRINT "Insufficient memory for mixing buffers": END CASE 9: PRINT "Insufficient memory for MSE file": END CASE 10: PRINT "MSE has invalid identification string (corrupt/non-existant)": END CASE 11: PRINT "MSE disk read failure": END CASE 12: PRINT "MVSOUND.SYS not loaded (required for PAS use)": END CASE ELSE: PRINT "Unknown error on MSE startup" + STR$(ErrorFlag): END END SELECTThis last section is a monstrous error-notice. If the ErrorFlag is 0, then the operation is a success. If anything goes wrong, the program will quit with an error. If this is not done, the computer will lock up. This could be trimmed to just quit if ANY error occurred.
IF LEN(COMMAND$) = 0 THEN INPUT "Module file: ", ModFile$ ELSE ModFile$ = COMMAND$Here is the example from MMP.BAS about how to specify a filename. All you have to do really is set ModFile$. This can be done in a number of ways, this is just one of them.
TestMOD: IF LEN(ModFile$) = 0 THEN END IF INSTR(ModFile$, ".") = 0 THEN ModFile$ = ModFile$ + ".GDM"This last fragment of code is MMP.BAS's way of 'testing' the filename.
IF EmsExist THEN ErrorFlag = 1 ELSE ErrorFlag = 0One of the greatest assets to BWSB is its use of EMS. It can allocate as much EMS as it needs to play sound files, up to the RAM limit in your computer.
File = FREEFILEA great way of determining a file handle to open is by using the FREEFILE command. It will open the next available file handle. Available file handles are set by the FILES line in CONFIG.SYS.
OPEN ModFile$ FOR BINARY AS FileGDM files are stored in binary format, so open it as such.
LoadGDM FILEATTR(File, 2), 0, ErrorFlag, VARSEG(ModHead), VARPTR(ModHead)Load that sucker up! And go through extensive error testing...
SELECT CASE ErrorFlag CASE 0 CASE 1: PRINT "Module is corrupt": END CASE 2: PRINT "Could not autodetect module type": END CASE 3: PRINT "Bad format ID": END CASE 4: PRINT "Out of memory": END CASE 5: PRINT "Cannot unpack samples": END CASE 6: PRINT "AdLib samples not supported": END CASE ELSE: PRINT "Unknown Load Error:" + STR$(ErrorFlag): END END SELECTErrors R Us...attempting to play a corrupt GDM file leads to disaster!
MusicChannels = 0 FOR J = 1 TO 32 IF ASC(MID$(ModHead.PanMap, J, 1)) <> &HFF THEN MusicChannels = MusicChannels + 1 END IF NEXTHere, the program uses a sneaky way of detecting how many channels to allocate. BWSB can allocate up to 32 channels, but unless you're using a GUS card, more channels means more CPU power.
OverRate& = StartOutput(MusicChannels, 0)Here, the output is initialized. Only one step left to getting the music going...
StartMusicHow simple! Whew! What a simple final step.
Now, when you wish to cancel the music, you should do this:
StopMusic StopOutput UnloadModule FreeMSEFreeMSE should only be used when you no longer need sound, like when you are ending the program. However, one of the nice things about QB is that FreeMSE is called when QB ends a program, so calling it is not really necessary. How- ever, it is ALWAYS a good idea to call it anyways...you just never know!
So, if you wish, just cut and paste the code into your program! It's that simple. Oh, and be sure to use the SETUP.EXE program that comes with the BWSB package to configure your MSE.CFG file. As it stands, using this code without an MSE.CFG file will make it lock up! So, use the SETUP.EXE or add error detection in the loading (more on that later...)
Woohoo! This completes the hardest part of using BWSB! If you can master this
then the rest is easy.
Secondly, in the last article I made an error. I said to put WAITFORKEY in the script.dat file but in the script.bas file we called it WAITKEY. Change WAITFORKEY in script.dat to WAITKEY.
Third, in this issue I'm gonna talk about variables and how to use them. You need the script.bas program and the script.dat file we created in issue #1 to use this article, if you don't have it I suggest you read the article in issue #1.
Unlike QBasic we're gonna have two types of variables, text and numeric. We're gonna modify our DISPLAYTEXT command so that it can handle variables and equations. First you need to add this two lines at the beginning of your script.bas file.
DIM SHARED Variables$(100,2) DIM SHARED VariableCount%What we've done is that we've made one arrays which hold the variable name, type and the value. VariableCount% controls how many variables we allready have in memory. Add this at the beginning of our script.dat file:
$text = Hello! This is Nightwolf's Scripting language article!! %a = 5 %b = 10 DISPLAYTEXT $text DISPLAYTEXT (%a * %b)This creates one text variable ($text) with the value of 'Hello! This is Nightwolf's Scripting language article!!' and two numeric values (%a and %b) with the value of 5 and 10. Then it displays the value of $text and displays the equation %a times %b. First we're gonna add variable detection and storage. Add this at the beginning of the DO...LOOP command just behind the reading of the line (just after
INPUT #1, ReadLine$):
IF LEFT$(ReadLine$, 1) = "$" THEN IF VariableCount% <= 100 THEN VariableCount% = VariableCount% + 1 Variables$(VariableCount%, 0) = LEFT$(ReadLine$, INSTR(ReadLine$, " ") - 1) Variables$(VariableCount%, 1) = "1" Variables$(VariableCount%, 2) = RIGHT$(ReadLine$, LEN(ReadLine$) - INSTR(ReadLine$, "=") - 1) END IF END IF IF LEFT$(ReadLine$, 1) = "%" THEN IF VariableCount% <= 100 THEN VariableCount% = VariableCount% + 1 Variables$(VariableCount%, 0) = LEFT$(ReadLine$, INSTR(ReadLine$, " ") - 1) Variables$(VariableCount%, 1) = "2" Variables$(VariableCount%, 2) = RIGHT$(ReadLine$, LEN(ReadLine$) - INSTR(ReadLine$, "=") - 1) END IF END IFI'm gonna explain the code line by line now.
IF LEFT$(ReadLine$, 1) = "$" THENIf the first character of ReadLine$ is a $ then it's a text variable and we start the IF.
IF VariableCount% <= 100 THENIf we've less than 100 variables in memory we continue.
VariableCount% = VariableCount% + 1Increases the number of variables in memory by 1.
Variables$(VariableCount%, 0) = LEFT$(ReadLine$, INSTR(ReadLine$, " ") - 1)Puts the name of the variable in Variables$. (name = all characters to the first space)
Variables$(VariableCount%, 1) = "1"Set the type of variable to 1 (text).
Variables$(VariableCount%, 2) = RIGHT$(ReadLine$, LEN(ReadLine$) - INSTR(ReadLine$, "=") - 1)Set the value of the variable to all the characters behind the = and the space following the =.
END IFEnd the IF
END IFEnd the IF
IF LEFT$(ReadLine$, 1) = "%" THENIf the first character of ReadLine$ is a % then it's a numeric variable and we start the IF.
IF VariableCount% <= 100 THEN
VariableCount% = VariableCount% + 1If we've less than 100 variables in memory we continue.
Variables$(VariableCount%, 0) = LEFT$(ReadLine$, INSTR(ReadLine$, " ") - 1)Puts the name of the variable in Variables$. (name = all characters to the first space)
Variables$(VariableCount%, 1) = "2"Set the variable type to 2 (numeric).
Variables$(VariableCount%, 2) = RIGHT$(ReadLine$, LEN(ReadLine$) - INSTR(ReadLine$, "=") - 1)Set the value of the variable to all the characters behind the = and the space following the =.
END IFEnd the IF.
END IFEnd the IF.
Displaying variables and equations
IF LEFT$(ReadLine$, 11) = "DISPLAYTEXT" THEN Temp1$ = RIGHT$(ReadLine$, LEN(ReadLine$) - 12) PRINT Temp1$ END IFAnd then replace it with this:
IF LEFT$(ReadLine$, 11) = "DISPLAYTEXT" THEN Temp1$ = RIGHT$(ReadLine$, LEN(ReadLine$) - 12) IF LEFT$(Temp1$, 1) = "$" OR LEFT$(Temp1$, 1) = "%" OR LEFT$(Temp1$, 1) = "(" THEN IF LEFT$(Temp1$, 1) = "(" THEN SELECT CASE MID$(Temp1$, INSTR(Temp1$, " ") + 1, 1) CASE "+" Action% = 1 CASE "-" Action% = 2 CASE "*" Action% = 3 CASE "/" Action% = 4 END SELECT Temp2$ = MID$(Temp1$, 2, INSTR(Temp1$, " ") - 1) Temp3$ = RIGHT$(Temp1$, LEN(Temp1$) - INSTR(INSTR(Temp1$, " ") + 1, Temp1$, " ")) Temp3$ = LEFT$(Temp3$, LEN(Temp3$) - 1) Temp2$ = LTRIM$(RTRIM$(Temp2$)) Temp3$ = LTRIM$(RTRIM$(Temp3$)) FOR i = 1 TO VariableCount% IF Variables$(i, 0) = Temp2$ THEN Temp1% = VAL(Variables$(i, 2)) IF Variables$(i, 0) = Temp3$ THEN Temp2% = VAL(Variables$(i, 2)) NEXT i SELECT CASE Action% CASE 1 PRINT Temp1% + Temp2% CASE 2 PRINT Temp1% - Temp2% CASE 3 PRINT Temp1% * Temp2% CASE 4 PRINT Temp1% / Temp2% END SELECT ELSE FOR i = 1 TO VariableCount% IF Variables$(i, 0) = Temp1$ AND Variables$(i, 1) = "1" THEN PRINT Variables$(i, 2) IF Variables$(i, 0) = Temp1$ AND Variables$(i, 1) = "2" THEN PRINT VAL(Variables$(i, 2)) NEXT i END IF ELSE PRINT Temp1$ END IF END IFI'll explain the code line by line now:
IF LEFT$(ReadLine$, 11) = "DISPLAYTEXT" THENIf the first 11 characters of the ReadLine$ variable are DISPLAYTEXT execute the DISPLAYTEXT command.
Temp1$ = RIGHT$(ReadLine$, LEN(ReadLine$) - 12)This gets the text, variable or equation to display from the ReadLine$ variable and stores it in Temp1$.
IF LEFT$(Temp1$, 1) = "$" OR LEFT$(Temp1$, 1) = "%" OR LEFT$(Temp1$, 1) = "(" THENIf the first character of Temp1$ is a $, % or ( then we start the variable/equation IF.
IF LEFT$(Temp1$, 1) = "(" THENIf the first character of Temp1$ is a (, start the equation IF.
SELECT CASE MID$(Temp1$, INSTR(Temp1$, " ") + 1, 1)Start a SELECT CASE command for the first character behind the first space in Temp1$. This is the equation method (+, -, *, /).
CASE "+" Action% = 1If it's a + (plus) then set Action% to 1.
CASE "-" Action% = 2If it's a - (minus) then set Action% to 2.
CASE "*" Action% = 3If it's a * (times) then set Action% to 3.
CASE "/" Action% = 4If it's a / (divide by) then set Action% to 4.
END SELECTEnd the SELECT CASE command.
Temp2$ = MID$(Temp1$, 2, INSTR(Temp1$, " ") - 1)The first variable name.
Temp3$ = RIGHT$(Temp1$, LEN(Temp1$) - INSTR(INSTR(Temp1$, " ") + 1, Temp1$, " "))Get the second variable name.
Temp3$ = LEFT$(Temp3$, LEN(Temp3$) - 1)Remove the last character from the second variable name because when we got it in the last step there still was the ) of an equation
Temp2$ = LTRIM$(RTRIM$(Temp2$))Remove all the spaces left and right from the first variable name.
Temp3$ = LTRIM$(RTRIM$(Temp3$))Remove all the spaces left and right from the second variable name.
FOR i = 1 TO VariableCount%Start a FOR...NEXT from 1 to the number of varialbes we have in memory.
IF Variables$(i, 0) = Temp2$ THEN Temp1% = VAL(Variables$(i, 2))If the variable names are the same make Temp1% equal to the value of the variable.
IF Variables$(i, 0) = Temp3$ THEN Temp2% = VAL(Variables$(i, 2))If the variable names are the same make Temp2% equal to the value of the variable.
NEXT iReturn to the FOR
SELECT CASE Action%Start a SELECT CASE of the value of Action%
CASE 1 PRINT Temp1% + Temp2%If Action% is a 1 (plus) then do the equation.
CASE 2 PRINT Temp1% - Temp2%If Action% is a 2 (minus) then do the equation.
CASE 3 PRINT Temp1% * Temp2%If Action% is a 3 (times) then do the equation.
CASE 4 PRINT Temp1% / Temp2%If Action% is a 4 (divide) then do the equation.
END SELECTEnd the SELECT CASE.
ELSEIf it's not an equation then:
FOR i = 1 TO VariableCount%Start a FOR...NEXT loop from 1 to the number of variables we have in memory.
IF Variables$(i, 0) = Temp1$ AND Variables$(i, 1) = "1" THEN PRINT Variables$(i, 2)If the variable names are the same and the type is 1 (text) print the value of that variable.
IF Variables$(i, 0) = Temp1$ AND Variables$(i, 1) = "2" THEN PRINT VAL(Variables$(i, 2))If the variable names are the same and the type is 2 (numeric) print the numeric value of that variable.
NEXT iGo back to the FOR
END IFEnd the if
ELSEIf it's not an equation or variable display:
PRINT Temp1$Just print the expression that was behind the DISPLAYTEXT command
END IFEnd the If
END IFEnd the If
DIM SHARED Variables$(100, 3) DIM SHARED VariableCount% OPEN "script.dat" FOR INPUT AS #1 DO INPUT #1, ReadLine$ IF LEFT$(ReadLine$, 1) = "$" THEN IF VariableCount% <= 100 THEN VariableCount% = VariableCount% + 1 Variables$(VariableCount%, 0) = LEFT$(ReadLine$, INSTR(ReadLine$, " ") - 1) Variables$(VariableCount%, 1) = "1" Variables$(VariableCount%, 2) = RIGHT$(ReadLine$, LEN(ReadLine$) - INSTR(ReadLine$, "=") - 1) END IF END IF IF LEFT$(ReadLine$, 1) = "%" THEN IF VariableCount% <= 100 THEN VariableCount% = VariableCount% + 1 Variables$(VariableCount%, 0) = LEFT$(ReadLine$, INSTR(ReadLine$, " ") - 1) Variables$(VariableCount%, 1) = "2" Variables$(VariableCount%, 2) = RIGHT$(ReadLine$, LEN(ReadLine$) - INSTR(ReadLine$, "=") - 1) END IF END IF ReadLine$ = LTRIM$(RTRIM$(ReadLine$)) IF LEFT$(ReadLine$, 11) = "DISPLAYTEXT" THEN Temp1$ = RIGHT$(ReadLine$, LEN(ReadLine$) - 12) IF LEFT$(Temp1$, 1) = "$" OR LEFT$(Temp1$, 1) = "%" OR LEFT$(Temp1$, 1) = "(" THEN IF LEFT$(Temp1$, 1) = "(" THEN SELECT CASE MID$(Temp1$, INSTR(Temp1$, " ") + 1, 1) CASE "+" Action% = 1 CASE "-" Action% = 2 CASE "*" Action% = 3 CASE "/" Action% = 4 END SELECT Temp2$ = MID$(Temp1$, 2, INSTR(Temp1$, " ") - 1) Temp3$ = RIGHT$(Temp1$, LEN(Temp1$) - INSTR(INSTR(Temp1$, " ") + 1, Temp1$, " ")) Temp3$ = LEFT$(Temp3$, LEN(Temp3$) - 1) Temp2$ = LTRIM$(RTRIM$(Temp2$)) Temp3$ = LTRIM$(RTRIM$(Temp3$)) FOR i = 1 TO VariableCount% IF Variables$(i, 0) = Temp2$ THEN Temp1% = VAL(Variables$(i, 2)) IF Variables$(i, 0) = Temp3$ THEN Temp2% = VAL(Variables$(i, 2)) NEXT i SELECT CASE Action% CASE 1 PRINT Temp1% + Temp2% CASE 2 PRINT Temp1% - Temp2% CASE 3 PRINT Temp1% * Temp2% CASE 4 PRINT Temp1% / Temp2% END SELECT ELSE FOR i = 1 TO VariableCount% IF Variables$(i, 0) = Temp1$ AND Variables$(i, 1) = "1" THEN PRINT Variables$(i, 2) IF Variables$(i, 0) = Temp1$ AND Variables$(i, 1) = "2" THEN PRINT VAL(Variables$(i, 2)) NEXT i END IF ELSE PRINT Temp1$ END IF END IF IF LEFT$(ReadLine$, 7) = "WAITKEY" THEN WHILE INKEY$ = "": WEND IF LEFT$(ReadLine$, 9) = "ENDSCRIPT" THEN EXIT DO END IF LOOP UNTIL EOF(1) CLOSE #1
Prerecorded FMV is what you will see mainly in computer-based games that span several CDs - although console games are also gaining much FMV now that cartridges are being phased out (even Nintendo will not use them for the new Dolphin system). Prerecorded FMV is just like what you see on your VCR when you play a movie. Everything has been done previously whether it was with live actors or in a 3D rendering program. Examples of games that have used this form of FMV include the "Wing Commander" series and "Final Fantasy VII." The downside to prerecorded FMV is that it hogs tons of memory if it isn't used sparingly. That's why the afore mentioned games are on several CDs. Real-time FMV is much never than prerecorded FMV because, until recently, personal computers and video game consoles had lacked the power necessary to generate quality movie on-the-fly. Nintendo has proven that this power barrier could be broken on their Nintendo 64 by releasing games like "The Legend of Zelda: The Ocarina of Time" and "Waverace 64." "Zelda" was only 32MB, including all the playable game and its 1.5 hours of real-time FMV! "Waverace" only has a very small amount of FMV - on the title screen - but still, if it would have been done as prerecorded FMV, it would not have fit onto the 8MB cartridge. Real-time FMV hogs processing power, but unlike prerecorded FMV, one can place hours of it in a game, taking only a small percentage of the space it would have taken otherwise.
There has been much debate over the years as to whether or not FMV adds to a game or hinders it. My personal belief is that cut-scenes enhance the game when placed between levels or areas, but when FMV is placed throughout the game, and it removes time from the game-play, that is when it is defeating it purpose. "Zelda" employs an excellent use of FMV to enhance the game by immersing the player in the game world. Whenever a new boss has to be introduced or the player brings Link to a new level, there is a short cut-scene. I have always been a fan of the "Final Fantasy" series, but I no longer am after Square slautered the series by releasing "Final Fantasy VII" on the Sony Playstation. (I've only seen a demo of the game on the PC, so I don't know if they have redeemed themselves yet.) The graphics in the playable portions of the game, to put it mildly, sucked. They reminded me of the mapscreen of Rare's "Donkey Kong Country" - which was good for its time, but now I'm looking forward to "Donkey Kong Country 64." :) Anyways, back to FFVII: You're playing the game in this environment with horrible graphics, and suddenly a FMV sequence begins. These sequences were all created on SGI workstations.making them extremely hig-quality, so the Playstation could never handle them in real-time, causing them to completely contrast the game and ruin any little immersion the player did get playing the game. So I guess my point is that if FMV is to be used in a game, it should seemlessly blend into the game so the feeling of immersion is not lost, and when it is put into a game, it should not be overused to the point where the person does not get to actually "play" the game because the whole point of buying a game is to be able to play it. If I'd want to watch a movie, I'd buy another ticket to see "The Phantom Menace." :)
Recently, games made in QuickBASIC have begun to gain FMV - both real- time and prerecorded - as powerful graphics libraries allow for it. One notable game is "Groov Buggies." The intro scene to it runs a loop of a prerendered sequences of some racecars running a circuit while music is playing. This was the first true FMV I'd seen in a QB game when I got Internet access a little over a year ago. Two of my games contain video sequences: "WarsTrek" and "The Mystical Journey." "WarsTrek" has laid dormant on my hard drive for several months as schoolwork has taken priority, but I did manage to get a short intro finished that shows a Type IV Shuttlecraft fleeing from the Millennium Falcon, dodging asteroids. TMJ has a few cinema sequences to introduce parts of the storyline (some may debate whether or not this is FMV because it's tile-based video). Many other QB games have intro sequences that use FLCs, AVIs, or are done in real-time, showing that it is very possible that FMV will be a standard in QB games by the end of this year.
Forward any comments to firstname.lastname@example.org, and if they aren't straight-out criticism or dissing, I'll be sure to reply.