Organization

If you have questions about any aspect of QBasic programming, or would like to help fellow programmers solve their problems, check out this board!

Moderators: Pete, Mods

Post Reply
Prosper
Newbie
Posts: 7
Joined: Thu Jan 07, 2010 5:29 pm

Organization

Post by Prosper »

I have two questions:

1. How do you organize your video game graphics/Sprites?

I have mine all listed out, Bit-mapped, and stored in their array in the main tier. They are organized like this:

========================================

':::SPRITES:::

'\\\RANDOM GUY///

[Read loop Goes here]

{Data Bitmap here}

["GET" command here]

' \\\Grass Tile///

[That stuff listed above]

''''''''''''MAPS'''''''''''

'***World One
'^^^Level One
' +++Map one
[Bitmap stuff]

============================================

So when the program is started, it quickly flashes all my graphics, then clears (I put the "CLS") and runs normally. I just wondered how others organized their game graphics, and/or if my way would slow down the run.


2. In a SIMPLE, "FOR DUMMIES" way, could someone please explain how I could use "BSAVE" and "BLOAD" to save my graphics into files?

Thanks ahead of time.

-Prosper
User avatar
bongomeno
Veteran
Posts: 266
Joined: Wed Dec 10, 2008 9:08 am
Location: Arizona
Contact:

Post by bongomeno »

This is how I usually organize my graphics...

EDIT: I forgot something in the code. imagedata: label

Code: Select all

REM Graphics data example by Bongomeno

REM Create and load image...

DIM image(10, 10)
RESTORE imagedata
FOR ry = 0 TO 9
FOR rx = 0 TO 9
READ image(rx, ry)
NEXT rx
NEXT ry

REM Display image...

LET xpos = 10
LET ypos = 10

SCREEN 13

FOR ry = 0 TO 9
FOR rx = 0 TO 9
IF image(rx, ry) THEN PSET (xpos + rx, ypos + ry), image(rx,ry)
NEXT rx
NEXT ry

END

REM Image data...

imagedata:
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,01,00,00,00,01,00,00
DATA 00,00,01,01,00,00,01,01,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,04,00,00,00,00,00,04,00,00
DATA 00,04,00,00,00,00,00,04,00,00
DATA 00,04,00,00,00,00,00,04,00,00
DATA 00,00,04,04,04,04,04,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
DATA 00,00,00,00,00,00,00,00,00,00
I would REALLY love to learn hwo to use BSAVE and BLOAD properly as well. :D
Last edited by bongomeno on Fri Jan 08, 2010 11:12 am, edited 1 time in total.
User avatar
BigBadKing
Veteran
Posts: 83
Joined: Fri Oct 09, 2009 12:39 pm
Location: Space
Contact:

Post by BigBadKing »

i mostly create rpgs (32x32 images), but here is the code anyway:

CODE:

Code: Select all

 dim grass(4 * (32 * 32) + 4)
 dim graph$(33)
 screen 12
 ' load graphics
 open "grass.dat" for input as #1
  for i = 1 to 32
   input #1, graph$(i)
  next i
 close #1
 ' draw graphics
 for y = 1 to 32
  for x = 1 to 32
   a$ = mid$(graph$(y), x, 1)
   ' check colors
   select case (a$)
    case "A"
     cl = 10
    case "B"
     cl = 11
    case "C"
     cl = 12
    case "D"
     cl = 13
    case "E"
     cl = 14
    case "F"
     cl = 15
    case "."
     cl = -1
    case else
     cl = val(a$)
   end select
   if cl <> -1 then pset(x,y), cl
  next x
 next y
 ' grab image
 get(1,1)-(32,32), grass(0)
 ' clear screen and draw new image!
 cls
 put(200,200), grass(0)
GRASS.DAT:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
this does the job instead of BSAVE and BLOAD for me!
<a href="http://mccorp.orgfree.com">Macselent Corporation Offical Site</a>
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

BSAVE saves the image contents of an Integer array up to 26K(1/3 of screen max) in Screen 12. Use the GET/PUT array's name. No more PUTing and GETing data to a file! Quite fast.:

Code: Select all

LB% = LBOUND(Array): bytes% = LEN(Array(LB%))
filesize& = ((UBOUND(Array) - LB%) + 10) * bytes% ' calculate file size

DEF SEG = VARSEG(Array(0)) 
BSAVE filename$, VARPTR(Array(LB%), filesize&
DEF SEG 'resets segment to QB default


'  ........BLOAD reloads the array data from the file:

DEF SEG = VARSEG(Array(0))
BLOAD filename$, VARPTR(Array(index%)) ' index to an array. Usually 0.
DEF SEG    
You can also use them to save ANY array type data including FIXED length strings or TYPE arrays. Variable length strings don't work without manipulation.

Ted
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
Prosper
Newbie
Posts: 7
Joined: Thu Jan 07, 2010 5:29 pm

Post by Prosper »

When you said 1/3 of the on-screen map is the limit size, I didn't know what you meant. Somewhere I read that you could have a four gig map, but only the on-screen portion would use memory, so I was planning to have a map near the size of the "Legend of Zelda" overground, with smaller maps from doorways and passageways.

I figured out how to use BSAVE and BLOAD (thanks a ton) all though I have to be using QB64 to run it when it does (my 64-bit computer requires me to run DOSBOX for Qbasic, which I prefer, but the mounted drive won't let you "BLOAD"). I much prefer Qbasic because separates subs, but I guess I can deall with QB64.

So. . .can I design a 4gig map like "LEGEND of ZELDA" and only worry about on-screen portions, or should I make each screen a separate map, and link them?
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

In QB, you can only GET one third of SCREEN 12 because of array size limitation of 32,767 elements. The screen also uses 4 planes. I use a 26K Integer array to hold the data.

So you can only GET a 640 X 160 portion of a fullscreen image at a time. Make a BSAVE loop to GET and BSAVE each portion to one of 3 filenames.

You cannot GET off of the screen so 639 is the actual max width since 0 is the minimum pixel coordinate. (0 TO 639 = 640). Same with depth. So the first row coordinate is 0 to 159. STEP 160 each loop.

Code: Select all


FOR y = 0 TO 320 STEP 160
         GET (0, y)-(639, y + 159), Image(0)
         FOR a& = 26000 TO 0 STEP -1 ' get the array size
               IF Image(a&) THEN ArraySize& = a&: EXIT FOR
         NEXT
         Num = Num + 1   'add to 7 digit file name by number 1, 2, 3 
         SaveName$ = SaveFile$ + LTRIM$(STR$(Num)) + ".BSV"
         BSAVE SaveName$, VARPTR(Image(0)), (2 * ArraySize&) + 200
NEXT y
QB64 has no screen array limitations. But it also can PUT any array data directly into a BINARY file:

Code: Select all

DIM myarray(80000) AS INTEGER
OPEN "myfile.ext" FOR BINARY AS #1
PUT #1, , myarray()
CLOSE #1
Variable string lengths will not work so use fixed length strings to save them. DIM Myarray AS STRING * 20

Ted
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
Prosper
Newbie
Posts: 7
Joined: Thu Jan 07, 2010 5:29 pm

Post by Prosper »

Alright, I got my sprites working, now updating is bothering me.

An example (Not Exact) of the code I'd use

Code: Select all

 
Do 
  Press$ = INKEY$
  IF Press = "w"
    DIR = 1
    IF HY > TopofScreen then HY = HY - 1
  -----The rest (a, s, d)-----
  END IF
  IF HY <> OLDHY
   CLS
   Call DRAWMAP
   Call DRAWHERO
   ENDIF
Loop



 
When I do this, there is a sort of animation (Basic is SLOOOOOWWW) of the map being drawn, tile by tile, then the Character looks jacked up.

On no background, my Hero looks fine, but on the map, he looks like the vomit of a drunk koala bear. ???
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

The map should load pretty fast with BLOAD even using 3 files. You don't have to reload it again either. Use a separate array to hold the character image and another to hold the background box area of the character.

I doubt your character looks like a box so you will have to make a mask for the character and save it to an array too. You can do the mask at the start of your program by PUTing the image: PUT(0, 0), Hero(0) on a black background. To create a mask, you alter the image to black and white only. This will keep colors from mixing using PUT XOR(the default):

Code: Select all

FOR xx = 0 TO 30  ' max column of box area
    FOR yy = 0 TO 30 ' max row of box area
        IF POINT(xx, yy) = 0 THEN PSET (xx, yy), 15 ELSE PSET (xx, yy), 0
    NEXT yy
NEXT xx
GET(0, 0)-(30, 30), Mask ' 31 X 31 box area
GET the box area to the mask array. Then place the map.

Set the position where the hero will start and GET the same box area as the hero from the map(without the hero!). You will use it to erase your hero when he moves.

So now we have the hero, mask and background placed in 3 arrays. Place the mask before the hero at the designated area. Don't forget to replace the background first!

Code: Select all

IF x <> px OR y <> py THEN ' draw the image at new position
   PUT(px, py), MapBG PSET ' pset covers any color without color mixing
   GET(x, y)-(x + 31, y + 31), MapBG ' get new BG before placing hero
   PUT(x, y), Mask AND  ' And allows background to show in all white areas. 
   PUT(w, y), Hero         ' PUT action is XOR default on top of the mask
END IF
px = x: py = y
When the hero moves, simply PUT MapBG(px, py) and move to the new coordinate placing mask and hero each move. px and py are the previous coordinate values to erase the previous hero image. I'd use px and py to check for a move so that it does not keep redrawing over and over.


Ted
Last edited by burger2227 on Sat Jan 09, 2010 4:22 pm, edited 1 time in total.
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
Prosper
Newbie
Posts: 7
Joined: Thu Jan 07, 2010 5:29 pm

Post by Prosper »

Oh my gosh, I never thought of drawing over the character BEFORE moving him. Thank you so much!

I have three more questions, if you wouldn't mind patronizing me:

1. The limited memory in QuickBasic, does it apply to the compiled file? I. e. Spore, a popular computer video game, written in C++, has no memory limit besides the memory on your computer, even though it's IDE may have had limits. Does this work with BASIC? As in, while the IDE (QuickBasic) may have memory limits preset, the compiled, stand-alone file doesn't? And what is the specific memory limit? 640K?

2. How do I put something OUT of memory. I BLOAD in my map, put it down, and thanks to you, got my walking engine working, but once I move to a new map, how to get the old map OUT of memory? Do I BSAVE it? I was thinking, if I made all the map files as numbers, and didn't correspond to the Array name:

Def seg = varseg (Map(0, 0))
BSAVE "010102.map", VARPRT (Map(0, 0)), 160

Could I do that so I can load my maps when I want them, and replace the previous one in the same array?

3. What is the preferred movement style? I attempted at "ZELDA-Freestyle" with Pixel-by-Pixel movement (Press "W" go up one pixel) or Tile by tile movement (with animations, so it's not jolty).

I've decided against scrolling by step, and to have four map portions, and ONLY scroll when transferring between them (Like NES ZELDA) (Best video game ever written).

Thank you so much for your time, I'll be giving you a credit at the end of the game ( I'll finish it, I've got everything done, except the engine).

-Prosper
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

640 K is the limit, but you can simply place a new map on the screen. I would BSAVE all of the maps into 3 files each. When you want a new map, just BLOAD the fullscreen files. No need to take memory out because the screen reserves that memory.

You can load each map portion into the same array you used with the first page. You just gotta remember which files are for what. Like Map11.BSV, Map12.BSV, Map13.BSV, Map21.BSV, etc. Fullscreen needs one 26K array to hold 1/3 of the data and PUT it on the screen. Once the maps are saved to files you NEVER have to draw them again!

One pixel at a time is probably too slow. In SCREEN 12, pixels are very small so you could try bigger moves. Try 5 pixels. That works pretty smooth. Want to move diagonally? Let me know!

Game programs can get pretty large! They may not compile over 100K modules. However you can CHAIN the modules to do different parts of the program or use QB64 to compile one BIG module. You may have to combine them if Qbasic runs out of memory. I use Notepad for that.

Ted
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
Prosper
Newbie
Posts: 7
Joined: Thu Jan 07, 2010 5:29 pm

Post by Prosper »

640k, got it, thanks.

However, what I meant by memory is, say I have 500 SHARED ARRAYS, won't that take a jimongogantis chunk of the 640k? Also, I'm in Screen 13, not 12, so the three files isn't something I have to worry about, I have one map filling most of the screen, with an area below and on the side for stats. Those 500 Arrays, that's my estimate of How many BLOADS I'm going to have, and each needs and array to hold what I BLOAD (that's just sprites, not even counting maps). So my main question is, will that take away from memory?

I'm not advanced enough to program in chains, or scripting engines or whatever, I have my .bas file, (which now contains all the subs, variables, etc. it ill have) and my sprite files (BSAVED). So, I'll probably do what you said and QB64 compile the ENTIRE butt-load, although QB64 catches errors in programs that run fine in Qbasic. . .

Also, if I do 1 (or five) pixels at a time, is there some formula to find what two tiles my "HERO" (Controlled Character) is on, so I can re-place those two when he moves?
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

You are limited in QB to integer array totals of 32,767 elements. That is not even considering memory that variables take.

In SCREEN 13, you can almost get the entire page. I'd just use 2 GETs of half the page in that case and BSAVE them. Your map array could be about 20K or less.

Are you using EVERY sprite on every level? If not, then share arrays to keep memory down. BLOAD can load the images quite fast. If some sprites don't move, then use one array for all of those.

The hero movement will need three arrays for him, the mask and the background to erase. Try to determine the smallest arrays possible without distortion. Use the backward loop in my BSAVE code above to determine how much space is used in an array. It returns the last data filled element(index). Adjust accordingly.

The movement going one or 5 pixels is the same. You use the keypresses to add or subtract an amount to the current screen coordinates each press. So nothing really needs to be added codewise. You can adjust that.

Ted
Last edited by burger2227 on Sun Jan 17, 2010 2:07 pm, edited 1 time in total.
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
User avatar
bongomeno
Veteran
Posts: 266
Joined: Wed Dec 10, 2008 9:08 am
Location: Arizona
Contact:

Post by bongomeno »

Does this BSAVE command apply to .bmp files? If I were to make a picture in ms-paint, how would I load that .bmp file?

This could be useful.
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

What SCREEN mode? SCREEN 12 or 9 can use 4 bit(16 colors), 13 can use 4 or 8 bit(256 colors) with colors. 24 BPP is only greyscale. So you have to save the Paint bitmap in those BPP (palette settings).

You need to use a bitmap loader program to place the image on the screen in QB. Since bitmaps use their own color settings, you have to index the RGB color settings into an array(at the beginning is best). Then index the GET Image after it. I have QB programs that can create BSAVE file(s) for you at: www.qbasicstation.com in the Member Files section or in my 4 Shared folder at the link below.

Screen 12 is good for drawings, cards, artwork or cartoons. 13 is best for pictures.

Ted
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
User avatar
Mentat
Veteran
Posts: 409
Joined: Tue Aug 07, 2007 3:39 pm
Location: NC, US

Post by Mentat »

bongomeno wrote:Does this BSAVE command apply to .bmp files? If I were to make a picture in ms-paint, how would I load that .bmp file?

This could be useful.
(Burger, remember this gem?)

There are two ways that I remember. FB just uses bload, otherwise you have create your own subroutine to load a .bmp manually. It's not that hard, actually, bitmaps are fairly straightforward to read from. I'm familiar with 32/24 bit stuff, but it's pretty much loading the image width and height from the header (byte offset 18 and 22? I might be off by one, you may have to play around with it first), and then the offset to the actual image data. That's where the pixel data is, and you may have to ask somebody else about the specifics on that, I'm not too familiar with that pixel data orienting thingamabob stuff.

Wiki link: http://en.wikipedia.org/wiki/BMP_file_f ... itmap_data
For any grievances posted above, I blame whoever is in charge . . .
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

The BMP header info is to byte 54. The palette colors follow. The size of the palette info depends on the BPP (bits per pixel) of the bitmap. 4 BPP (16 colors) needs 64 bytes. 8 BPP (256) colors is 1024 bytes. The start of image data follows. The offset can be found in the header info.

I have more info if needed.

Ted
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
User avatar
coma8coma1
Veteran
Posts: 100
Joined: Sat Dec 08, 2007 5:29 pm
Location: Maryland, USA

Post by coma8coma1 »

I'm running SCREEN 13 with a custom palette.

I'm storing all my "GET"ted data in txt files. My tile editor just GETs the data into an array and dumps that to the file. When a level loads up it simply loads up the appropriate files into the gfx tile array and the game PUTs them as needed.

That's for tiles. For sprites it stores strings containing the ASCII characters (one char per pixel) pertaining to each color. That's ASCII 0-255 representing 0-255 colors. The only problem is character #26 which QB interprets as an "EOF" end of file indicator and therefor color 26 can't be captured. I use this for sprites because when the game draws these graphics back out onto screen it ignores color #0 which i'm treating as transparent.

Kind of archaic and n00bish, but I came up with it by myself over 10 years ago with no formal training. maybe my next game will be better?
Post Reply