Scrolling tile RPG

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

MilesAway1980
Coder
Posts: 25
Joined: Tue Jul 29, 2008 12:30 pm

Scrolling tile RPG

Post by MilesAway1980 » Thu Jul 31, 2008 5:20 pm

Hello everyone,
I've been working on a QBasic RPG for quite a few years now. It uses a smooth scrolling map (ie Final Fantasies for the SNES), but the one thing that's always bugged me is that I just can't get it to scroll smooth enough. Right now, my tiles are saved in string files, so that all I have to do is load each tile from the file and then DRAW it anywhere I want. It works great, and looks great, but isn't the fastest.

The reason I went with this route is because using the GET and PUT commands cause an error if any portion of it is printed outside of the VIEW SCREEN. If my tiles are 20 x 20, and I try to place a tile at (310, 100), it obviously errors.

The other method I tried using was PSET, where it draws every pixel of every tile individually when the screen moved, but this was WAAAAAY to slow.


Does anyone know a way to use GET and PUT and have them outside of the VIEW SCREEN? This would really help. If not, does anyone know some assembly code I could use to create my own fast GET and PUT that would print outside the VIEW SCREEN? I would really rather not use libraries.

Thanks for any help! I've just put a lot of work into it and it would suck to just have it unplayable because its annoying to look at.

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

NOPE

Post by burger2227 » Thu Jul 31, 2008 5:32 pm

PUT and GET must use Coordinates on the screen. Otherwise you get an error! If you cannot see the stuff, you cannot GET it and why do you want to PUT things offscreen?

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

MilesAway1980
Coder
Posts: 25
Joined: Tue Jul 29, 2008 12:30 pm

Post by MilesAway1980 » Thu Jul 31, 2008 6:52 pm

:? Yeah...I know I get an error. That's why I asked how there was a way to do it without getting one.

The reason why I want to PUT things off screen is because its a smooth scrolling map. So that while its scrolling, I want half of a tile to be visible while half of it isn't, that way it can scroll of screen, and not just disappear as soon as it gets to it. That looks pretty crummy.

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

Post by burger2227 » Thu Jul 31, 2008 8:26 pm

Try using BSAVE files and BLOAD. GET can load the info into an Array and then you can BSAVE that info to a file. To Load a portion, just BLOAD it back and PUT it again. BLOAD and PUT work very fast.

Naturally, you may need a large integer Array, according to GET area size and screen mode. Use DEFINT A-Z if the array is large, but it's size cannot be over 32K. Screen 12 can capture up to 1/3 of the screen in an Array of 26K. Screen 13 can GET over half

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

MilesAway1980
Coder
Posts: 25
Joined: Tue Jul 29, 2008 12:30 pm

Post by MilesAway1980 » Fri Aug 01, 2008 8:16 am

I must not be making myself clear. For my game to work, I need to be able to draw a tile partially on screen and partially off screen. That way it can scroll smoothly (with the character constantly staying in the middle of the screen.)

I know how BSAVE and BLOAD work and how to access pictures from a file, that's not the point. I just need to figure out a way to draw them to the screen where part of them is visible and part of them isn't without getting a crash. I know that using the PUT statement for that does crash, so I am wondering if anyone knows a different way to do it.

Ralph
Veteran
Posts: 148
Joined: Fri Feb 09, 2007 3:10 pm
Location: Katy, Texas

Post by Ralph » Fri Aug 01, 2008 2:35 pm

MilesAway:

Please see my post in the thread, PAINT COMMAND. There, I show that you can use a very simplified method for any CHR$(N), for N = 32 up to 265. Well, 32 through 125 (the available characters on the keyboard). Maybe that can help you out.

As o your desire to PAINT tiles off the screen...hmmm, assuming you scroll 4 bits at a time, how about creating some half-length tiles, which would be PUTed when you scroll up to the 4-bit limit?

If the above doesn't work, maybe you could use the partical screen 8-632 by 8-472, with the 8-pixel border areas colored black (as if to say, we are using a somewhat smaller scrren than the full 640x480 one). Then, a suitable subroutine or SUB could take care of re painting the particular 8-pixel strip AFTER PUTting the intruding tile.

User avatar
TmEE
Veteran
Posts: 97
Joined: Mon Mar 17, 2008 11:14 am
Location: Estonia, Rapla
Contact:

Post by TmEE » Fri Aug 01, 2008 4:08 pm

I would have used custom assembly PUT routines, which draw into a double buffer, and which you load to frame buffer once you're done with all drawing stuff... if the assembly routines are fast, your scrolling is fast, and with the double buffer, you will not have to worry about flickering.
I'm lately programming more in assembly than in any high level language....
Mida sa loed ? Nagunii aru ei saa :P

MilesAway1980
Coder
Posts: 25
Joined: Tue Jul 29, 2008 12:30 pm

Post by MilesAway1980 » Fri Aug 01, 2008 5:43 pm

Ralph wrote:MilesAway:

Please see my post in the thread, PAINT COMMAND. There, I show that you can use a very simplified method for any CHR$(N), for N = 32 up to 265. Well, 32 through 125 (the available characters on the keyboard). Maybe that can help you out.

As o your desire to PAINT tiles off the screen...hmmm, assuming you scroll 4 bits at a time, how about creating some half-length tiles, which would be PUTed when you scroll up to the 4-bit limit?

If the above doesn't work, maybe you could use the partical screen 8-632 by 8-472, with the 8-pixel border areas colored black (as if to say, we are using a somewhat smaller scrren than the full 640x480 one). Then, a suitable subroutine or SUB could take care of re painting the particular 8-pixel strip AFTER PUTting the intruding tile.
These are some things I had thought of (except for the PAINT command, since my tiles are all actual pictures I created in an editor I made). I have thought about making some half tiles, and that is definitely an option, but it is also a lot of extra extra work. If I had 200 tiles in my game, I would have to make 200 full tiles, 200 half left, 200 half right, 200 half top, 200 half bottom, 200 top right corner, 200 top left corner, 200 bottom right corner, and 200 bottom left corner. Right now I already have 60 and I've barely gotten anywhere.

As for drawing them and then having a routine that draws over the top of them. I've tried that too. The downside is that you can see the tile for a flicker of a second while its being drawn to the screen, so there's always a flash of disappearing, reappearing tiles around the border.

TmEE wrote:I would have used custom assembly PUT routines, which draw into a double buffer, and which you load to frame buffer once you're done with all drawing stuff... if the assembly routines are fast, your scrolling is fast, and with the double buffer, you will not have to worry about flickering.
I'm lately programming more in assembly than in any high level language....
Do you know of a custom assembly PUT routine? This is something I would definitely be interested in using. However, I know nothing of assembly what-so-ever, so I wouldn't even begin to know where to start.

Ralph
Veteran
Posts: 148
Joined: Fri Feb 09, 2007 3:10 pm
Location: Katy, Texas

Post by Ralph » Fri Aug 01, 2008 7:26 pm

MilesAway wrote:
As for drawing them and then having a routine that draws over the top of them. I've tried that too. The downside is that you can see the tile for a flicker of a second while its being drawn to the screen, so there's always a flash of disappearing, reappearing tiles around the border.
I think that if you make just two color 0 "tiles", one vertical 8x480 , the other 624.8 (for SCREEN 12), and GET them at the beginning. you can PUT them as required, and NOT have any flicker. At least, in my limited use of PUTs, I don't see the flicker when I erase a sprite by PUTting the area that i GETed before the sprite moved there, and then PUTting the sprite in the new location. However, as I said, I have done very limited graphics work. Perhaps you could give it a try, and report back how it went?
Ralph, with QuickBASIC 4.5, operating under Windows XP, wiht anHP LaserJet 4L Printer. Bilingual in English/Spanish

MilesAway1980
Coder
Posts: 25
Joined: Tue Jul 29, 2008 12:30 pm

Post by MilesAway1980 » Mon Aug 04, 2008 11:10 am

Ralph wrote:MilesAway wrote:
As for drawing them and then having a routine that draws over the top of them. I've tried that too. The downside is that you can see the tile for a flicker of a second while its being drawn to the screen, so there's always a flash of disappearing, reappearing tiles around the border.
I think that if you make just two color 0 "tiles", one vertical 8x480 , the other 624.8 (for SCREEN 12), and GET them at the beginning. you can PUT them as required, and NOT have any flicker. At least, in my limited use of PUTs, I don't see the flicker when I erase a sprite by PUTting the area that i GETed before the sprite moved there, and then PUTting the sprite in the new location. However, as I said, I have done very limited graphics work. Perhaps you could give it a try, and report back how it went?

It does start to flicker when you PUT 160 tiles every time the screen moves and then draw over them. Even if its not every time, it'll still flicker. Also, I'm using Screen 13.

Ralph
Veteran
Posts: 148
Joined: Fri Feb 09, 2007 3:10 pm
Location: Katy, Texas

Post by Ralph » Mon Aug 04, 2008 4:41 pm

OK, instead of the vertical 8x480 and 624x8, for SCREEN mode 12, use a vertical 8x200, and a horizontal 304x8 black (background) tile, that is only TWO tiles. What are you talking about when you say 160 tiles? Perhaps you are talking about the whole screen? Because dividing all the pixels of SCREEN 13, namely, 320x200, by the pixels in one 20x20 pixels tile does give me 160 tiles. So, it would seem you are redrawing the screen here.

The only thing I was trying to help you wth was your trying to load a partial tile at one of the fours sides. So, my question on this is, did you try it? Modified as i explained above for SCREEN mode 13.
Ralph, with QuickBASIC 4.5, operating under Windows XP, wiht anHP LaserJet 4L Printer. Bilingual in English/Spanish

MilesAway1980
Coder
Posts: 25
Joined: Tue Jul 29, 2008 12:30 pm

Post by MilesAway1980 » Mon Aug 04, 2008 5:00 pm

Yeah, I tried that. Made two black tiles to lay over the top of the others. It was still pretty visibly flickery.
And yeah, it's 160 tiles due to the entire map redrawing every time the character moves, (320x200, 20x20 tiles). It's necessary to redraw the whole map since the map moves, not the character.

The problem with drawing a border to straighten it out (which does look good once its done drawing), is that since it does indeed draw every tile, there will be a moment on screen when the edge tile is visible until the border is drawn over it.


I'm probably going to need some type of fast assembly custom GET and PUT routine to make this work. Just not sure how to make one myself.

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

Post by burger2227 » Mon Aug 04, 2008 7:16 pm

I think redrawing the entire screen is AWFUL slow to begin with! Moving the background and not the character is biting off way more than you can probably chew.

Perhaps you should rethink the whole idea. This stuff is not for the weak of heart or beginners! Try page flipping in SCREEN 7. (16 colors)

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

Ralph
Veteran
Posts: 148
Joined: Fri Feb 09, 2007 3:10 pm
Location: Katy, Texas

Post by Ralph » Mon Aug 04, 2008 8:15 pm

I haven't done any considerations for a moving background! I do have a .bas program, called QMANCHE, which has a constantly scrolling forest and buildings. It seems very jumpy, though. I, personally, haven't tried to deciher how the code works. It seems to me o be very tight code, and, pleanty of it! If interested, email me, and I'll send you a copy. Then, if you are really, reslly interested, I might be coerced into trying to understand just how that program was done.
Ralph, with QuickBASIC 4.5, operating under Windows XP, wiht anHP LaserJet 4L Printer. Bilingual in English/Spanish

Ralph
Veteran
Posts: 148
Joined: Fri Feb 09, 2007 3:10 pm
Location: Katy, Texas

Post by Ralph » Mon Aug 04, 2008 8:50 pm

Yeah, Burger knows what he is talking about! I just went through one program that redrew the screen each time, and it was a stationary screen! After various intents of having the OP (original poster) take my suggestions of just moving his scout (the sprite), I finally ended up changing his code to do so, using GETs and PUTs. However, as I said, that was a stationary screen. As to moving screens, paging (as suggested by burger) might help, but, I don't think that paging will do it with a moving screen, unless it's pretty repetitious.

As you pointed out, we probably need some big-guns guru here that's been there, and now knows just what is required.
Ralph, with QuickBASIC 4.5, operating under Windows XP, wiht anHP LaserJet 4L Printer. Bilingual in English/Spanish

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

Post by burger2227 » Mon Aug 04, 2008 9:22 pm

Screen 7 has pages 0 up to 7, or 8 pages you can draw small areas. Just add pieces at a time to make it look like it is scrolling. Naturally you could also use the pages to add background stuff, like bushes or hazards.

You could also use WAIT to decrease flicker.

A BIG PROJECT! I don't do games often.

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

Ralph
Veteran
Posts: 148
Joined: Fri Feb 09, 2007 3:10 pm
Location: Katy, Texas

Post by Ralph » Mon Aug 04, 2008 9:45 pm

Burger, are you familiar with qmanche? The .bas file is abou 22K. Is that too big to post here? That is, if you are interested in it. To me, the code is very difficult! Of course, if I dedicate a lot of time, I could probably learn how some of the code does what it does, but, right now, I don't have any inclination to try to tackle it, ha, ha!

Edoted by Ralph:
Oh, I just found a program by Bodemss called Scroll.bas. It does a horizontal scroll in SCREEN 13, using 8 pages and two colors only, black background and blue foreground. Moves fairly nice, at 100 fps (frames per scond..does that mean, screens per second?)

MilesAway1980
Coder
Posts: 25
Joined: Tue Jul 29, 2008 12:30 pm

Post by MilesAway1980 » Tue Aug 05, 2008 10:14 am

Hey everyone,
Thanks for all the info. This is definitely not something that I just started up. I've been tinkering on the game for almost 8 years. If I still had Windows 98, I'd take some screen shots for you, but XP doesn't let you shrink the screen down the way it used to.

Currently, the game is about 2 - 3MB in size, so its not something I'm about to start over for different screen sizes. The main reason I bring these questions up now, is that the longer I work on it, the better I want it to look, and the better it looks, the slower it runs!

My other goal was to completely program the game in 100% QBasic. No libraries, etc. On the other hand, when it starts to get a little choppy, I realize that no one's going to want to play my hard work if its annoying to look at.

I've tried Screen 7, but its amazing just how slowly it runs. That and it allows for only 16 colors, when my game currently puts to use a whole lot more than that.


I think I might have figured something out though that helped a lot. Originally, with the technique I was using where each tile was a text string that was loaded and then drawn using the DRAW command, the slowest part about it was loading the text string from a file every time. However, I thought of a routine last night where after it loaded the string, it searched through every tile on the map and if it was the same tile, it would draw it. So, now it runs about 170% faster, which is nice. :)

For example, instead of going through what was on screen and going:

tile = grass
load "grass" from file
Draw grass

tile = mountain
load "mountain" from file
Draw mountain

tile = grass
load "grass" from file
Draw grass
...
...
...

It now goes
tile = grass
load "grass from file
Search entire screen for all uses of grass
Draw grass
draw grass
draw grass
...
...
...


And so on. Much faster! Hope that makes sense. :)
Last edited by MilesAway1980 on Tue Aug 05, 2008 10:31 am, edited 1 time in total.

MilesAway1980
Coder
Posts: 25
Joined: Tue Jul 29, 2008 12:30 pm

Post by MilesAway1980 » Tue Aug 05, 2008 10:30 am

If your curious of an example map, and how the DRAW works, here's an example:

Use the Arrow keys to move, and use the "+" and "-" keys to change the time of day.


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

DEFINT A-Z
SCREEN 13
Info$="C2R4C100RC2R3C102RC2R4C103RC2R2C101RC103RC102RC2
DL2C101LC100LC2LC102LC2L2C101LC2LC102LC101LC2LC103LC2L5DR4
C101RC2R3C21RC18R2C21R6C2RC100RC102DC2LC103LC21LC20LC22L
C19L4C18L2C19LC21L3C100LC2L3DR2C101RC2RC21RC20R2C19RC22R2
C18RC19R2C22R3C20R3C2DC100LC19LC20L3C22L2C19LC21LC18LC23L
C22L2C20LC19L2C21LC19LC2LDC103RC19R3C21R2C20RC21RC20R2
C22RC21RC22RC20R3C21RC20RC19RC2DC101LC19LC20LC21LC20L
C23LC20L2C22LC20L5C21L2C22LC19LC20LC2DRC19RC20RC22RC21R2
C20R2C21R3C20R2C23R2C22RC21RC19R2C2DLC19LC20LC19LC22L2
C23L3C20L5C21LC20L2C19L2C2DRC19R2C20RC19RC20R5C23R4C22R2
C21RC20RC19RC2DC102LC19LC20LC21L2C19LC22LC23L3C24L2C23L2
C22LC21LC20LC19L2C2DRC19RC18RC20RC21RC22RC23R2C24R2C23R2
C21RC22R2C21R2C20RC19RC2DL2C20LC21L2C22L2C23L2C24LC21L
C24LC23LC22L2C18LC20LC19L2C2DC103RC19R2C20RC21RC22RC19R2
C24R3C23R2C22R2C21RC2R2C103RC100DC103LC2LC103LC2L2C102L
C22LC23LC24LC23LC24L2C19L2C22LC20L2C19LC2LDR2C103RC20R
C21RC22RC19R2C24R2C23R2C101RC2R3C100RC2RC101RC2DLC100L
C2L3C101LC2L2C100LC2L3C103LC2L4C102LC2LC101DC2RC103RC2R2
C100RC2RC101RC2R4C103RC101RC2R2C102RC2R2C100RC2DL3C103L
C2L4C102LC2LC101LC2LC103LC101LC2L5nm+0,0"

Info2$="C102R2C103RC2R5C103RC2RC102RC2R4C100RC2R3C103DL
C2LC103LC2LC100LC2L2C103LC2LC102LC2LC103LC2LC102LC2L3C103L
C102LC2DRC102RC103RC102RC2R2C102RC2R3C102RC2RC103RC2R2
C102RC2RC103RC2RC103DC2L2C103LC2LC102LC2L2C103LC2LC102L2
C2L2C102LC2L2C102LC2LC102LC2DC102RC2R2C102RC100RC2RC102R
C2RC100RC102R2C2R2C101RC2RC102RC2RC103RC2RDL4C102LC2L5
C102LC100LC2L3C100LC2L3C102DRC2R3C100RC2R3C100RC102RC2R5
C102RC2R3C102DLC2L5C101LC2L4C100LC2LC103LC2LC100LC2L3C102
DC2R4C100RC2RC103RC2RC100RC2R2C102RC2RC101RC2R2C102R
C2R2C102DLC2LC100LC102LC2LC102L2C2LC102LC100LC2LC100LC2L
C103LC2LC100LC2L3DR6C100RC2R3C100RC102RC2R2C102RC2R
C102RC100RC2RC102DC2L2C100LC102LC2LC102LC100LC2LC102L2
C2L3C100LC2LC103LC2LC100LC2LDR2C100RC2RC103RC2RC100R
C2R2C100RC2RC103RC2RC100RC102RC2R2C100RC2RDL5C102L
C100LC2LC103LC2LC100LC2L2C100LC2LC103LC2L3DR3C100RC103R
C2R4C100RC2RC103RC2RC100RC102RC2R4DL6C100LC2L3C100LC2L3
C100LC2LC100LC2L2DR3C100RC2RC100RC2R3C100RC2RC102RC2R
C100RC2R5DL8C102LC2L2C103LC2L2C100LC2L3C102LC2DRC102R
C103RC2R2C100RC2R2C103RC2R2C102RC2R3C100RC2R3C103DL
C2L3C100LC2L3C102LC2L2C103LC2L2C100LC2L2C103LC102LC2nm+0,0"

TimeOfDay = 20

DO

x$ = INKEY$
IF x$ = "=" OR x$ = "+" THEN : TimeOfDay = TimeOfDay + 1
IF x$ = "-" OR x$ = "_" THEN : TimeOfDay = TimeOfDay - 1
IF TimeOfDay > 40 THEN : TimeOfDay = 40
IF TimeOfDay < 0 THEN : TimeOfDay = 0
WAIT &H3DA, 8
FOR x = -2 TO 17
FOR y = -2 TO 11
XPos = x * 20 + XMove
YPos = y * 20 + YMove
PSET (XPos, YPos)
IF y = 5 AND x = 5 THEN
DRAW Info$
ELSE
DRAW Info2$
END IF
NEXT
NEXT

CIRCLE (160, 100), 4, 4
PAINT (160, 100), 4, 4

IF x$ = CHR$(0) + "K" THEN : XMove = XMove + 1
IF x$ = CHR$(0) + "M" THEN : XMove = XMove - 1
IF x$ = CHR$(0) + "P" THEN : YMove = YMove - 1
IF x$ = CHR$(0) + "H" THEN : YMove = YMove + 1
IF x$ = CHR$(27) THEN : END


PALETTE 2, 256 * (TimeOfDay + 2)
PALETTE 100, 256 * (TimeOfDay + 3)
PALETTE 101, 256 * (TimeOfDay + 4)
PALETTE 102, 256 * (TimeOfDay + 1)
PALETTE 103, 256 * TimeOfDay

LOOP

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




Keep in mind that I made a tile editor that makes those text strings! I didn't do them all by hand. :) You'll also have to put the text strings on one line and in one text string in QBasic (probably a lot easier if done while its still in a text editor!). I simply edited them in this to make them easier to see.

User avatar
TmEE
Veteran
Posts: 97
Joined: Mon Mar 17, 2008 11:14 am
Location: Estonia, Rapla
Contact:

Post by TmEE » Tue Aug 05, 2008 11:10 am

few tips :

Use a CASE SELECT instead of the bunch of IFs that deal with movement of player, and maybe use INP(&H60) instead of INKEY$...
Mida sa loed ? Nagunii aru ei saa :P

Post Reply