Jump to content
IGNORED

Smooth Horizontal Scrolling (messing with wsync)


Gemintronic

Recommended Posts

In a different topic I posted this:

 

I guess it would have already been invented some time ago.. but, I wonder if the start of playfield drawing could be moved horizontally. You could fake smooth scrolling that way I bet. I've already played around with changing wsync to create longer/shorter playfield blocks. Maybe that's a lead?

 

 

Note that I have no idea what I'm doing or what I'm talking about. I just noticed that playing with SeaGtGruffs color bar example that I would vary the sizes of "playfield pixels" by taking longer or shorter durations to change the color.

 

I was wondering if this is actually an avenue to create smooth horizontal scrolling by varying the start position of drawing.

 

I mean, if the first column of playfield blocks was drawn longer then the next of the playfield pixels would look like the screen is moving east, right?

Link to comment
Share on other sites

I'm not certain what you're suggesting, but I think the answer is either "no" or "not really, at least not easily," depending on what exactly you're suggesting.

 

If you're wondering whether there's a way to delay the start of the playfield drawing process, no there isn't. The playfield pixels are drawn at specific locations across the screen as counted from the beginning of horizontal blanking and as controlled by the "horizontal sync counter." The only way to shift the playfield pixels a little bit left or right would be to somehow change the horizontal sync counter during its count, which can't be done. You can reset the counter by writing to the RSYNC register, but that would just make the current line end sooner than expected; the playfield pixels will still line up as normal after the short line.

 

Note that my palette examples don't use the playfield; they just change the background color (COLUBK) as the lines are drawn. Color changes must happen on specific 3-pixel boundaries, due to the fact that 1 machine clock equals 3 pixels or color clocks. So if you draw the "playfield" by changing the color registers, you can shift the color changes by 3 pixels by changing how long you wait before you start making the changes. However, 3 color clocks aren't much smaller than 4 color clocks-- i.e., the width of a playfield pixel-- so you wouldn't be gaining much by "scrolling" 3 color clocks rather than 4. Also, to draw a "playfield" by this method you'd need to devote almost all of the scan line to changing the background color, which raises three different problems-- (1) there wouldn't be much time left for drawing anything else; (2) the "playfield" pixels would be wider than normal due to the time it takes to write to a color register; and (3) to draw the "playfield" you'd probably need to put the screen kernel in expansion RAM and "unroll" it so you can set different colors at different positions.

 

I've actually been toying (on "paper," or rather in Notepad) with an idea for a simplistic "RPG map screen" that draws the screen using background color changes rather than the playfield. Each "block" would be a square that's 9 color clocks wide and 15 lines tall, and would be drawn by repeatedly writing to COLUBK using STY, STA, STX, or SAX, giving four possible colors-- although the fourth color (SAX) would be the logical AND of two of the other colors. By changing the colors from line to line, the colors could be mixed with each other. And by using two different palettes on alternating lines, the color mixtures could be different:

 

Odd lines - STY1, STA1, STX1, SAX1

Even lines - STY2, STA2, STX2, SAX2

 

Color combinations:

STY1/STY2, STY1/STA2, STY1/STX2, STY1/SAX2

STA1/STY2, STA1/STA2, STA1/STX2, STA1/SAX2

STX1/STY2, STX1/STA2, STX1/STX2, STX1/SAX2

SAX1/STY2, SAX1/STA2, SAX1/STX2, SAX1/SAX2

 

Then by varying the time before the first "block" is drawn, the "blocks" could be shifted 3 color clocks at a time, such that each "block" scrolls a third of its width at a time and it takes 3 frames to scroll the screen "1 full block."

 

My plan (on paper) is to have the kernel be in expansion RAM, either with three different versions to allow the scrolling, or some other way to vary the start time using a single kernel. And even with just "one" kernel, I figure there might need to be two copies, so the second copy can be updated while displaying the first, then display the second copy after it's been updated and start changing the first copy-- that is, if the screen is being scrolled; if the screen isn't being scrolled, then just keep displaying the current copy.

 

The nice thing about STY, STA, STX, and SAX is that they're almost the same machine codes-- $84 (STY zp), $85 (STA zp), $86 (STX zp), and $87 (SAX zp). So my plan is to basically start with a "dummy" kernel that just does STY COLUBK over and over again, then use ORA or some other method (maybe just INC?) to change the STY machine codes to STA, STX, or SAX depending on the color desired. That way the map data could be stored using 2 bits per block, or 4 blocks per byte, and the pixel value (%00, %01, %10, or %11) could be added to the STY code to get STY, STA, STX, or SAX. Of course, you'd need two copies of the map data if you're going to mix colors-- one for the odd lines, and one for the even lines.

 

Although it should be possible (if a lot of work) to create a scrolling RPG map this way, the real difficulty would be putting the player sprites on the map. As long as the player's sprite is always in the center and the map scrolls as he (or she) moves around, drawing the player's sprite wouldn't be too much trouble-- just position that sprite at a fixed horizontal location, and draw it on the same lines vertically. But using the other sprite for other objects, like towns or castles, would be problematic, because you'd be so busy drawing the map that you wouldn't have time to reposition the other sprite on different rows. You could get around that by designing the map so only one copy of the other sprite is ever needed on the screen, but that would mean the towns and castles would have to be separated from each other on the map so that only one of them would ever be visible at a time as the map is scrolled. And that doesn't solve the problem of going into a town or castle and having a bunch of other people wandering around for you to talk to.

 

Another problem is that if you're drawing the screen with just the background color, there's nothing for the player's sprite to collide with. So the only way to have some blocks be "impassable" would be to have a third copy of the map that stores the type of terrain rather than the color indexes-- i.e., does the block allow free movement, or is it impassable, or is movement slowed down in that block, or does being on that block take away a hit point each turn (e.g., moving through a poisonous swamp).

 

So even though it should be possible to draw a scrolling map this way, there are a lot of problems that would need to be solved for it to be useful for creating an actual RPG game.

Link to comment
Share on other sites

I guess that's another reason the Strongbad RPG never completed.

 

Thank you for the detailed answer to my nebulous, newbie question SeaGtGruff =)

 

P.S. I wouldn't mind having a collision map and just two sprites: one centered and the other for a detailed object. Especially if the background looks like it's smoothly scrolling horizontally :)

Link to comment
Share on other sites

A while ago I played around with this. In the attached demo (scroll1) I use big blocks so there is time left for sprites. There are about 16 cycles left in the kernel for displaying other stuff. Its buggy, but you can scroll to the right/bottom (weird things can happen if you scroll upwards :)).

 

In scroll2.bin I tried filling the playfield with:

LDA (ZP0),Y

STA COLUBK

LDA (ZP1),Y

STA COLUBK

LDA (ZP2),Y

STA COLUBK

etc.

This kernel has 67 spare cycles between lines

scroll.bin

scroll2.bin

post-15728-0-46974500-1384925883_thumb.png

post-15728-0-03526500-1384925969_thumb.png

Edited by roland p
  • Like 1
Link to comment
Share on other sites

You can get smooth horizontal scroll with playfield simply doing it at 30 fps, of course not in pixel scrolling but as the smallest resolution of playfield that is the 4 pixels used by each playfield pixel.

 

I think I already have per-playfield-pixel handled. Is what I'm doing what yer talking about?

http://atariage.com/forums/topic/218190-smooth-vertical-scrolling-from-data-want-4-way/

 

I think what these guys just demonstrated goes beyond that. Unless my eyes fool me (and they do often) they are achieving something that looks like per pixel horizontal scrolling.

Link to comment
Share on other sites

Unless my eyes fool me (and they do often) they are achieving something that looks like per pixel horizontal scrolling.

It is not per pixel scrolling, but per 3 pixel scrolling (in the horizontal direction), that is the highest resolution you can get when you use the COLUBK register to draw a playfield. The obvious benefit is that you can have more than 2 colors on a scanline.

 

Your eyes are fooled when the screen scrolls 3 pixels each frame.

 

If you sacrifice P1/M1 and set them to 3 copies wide, you can use them to create a pattern that can mask the 3-pixel inacuracy and achieve 1 pixel acuracy. See attached demo to see what I mean, you can play around in stella and enable/disable P1/M1 with alt-x/alt-v. It's a bit rough but it does the job.

post-15728-0-26869200-1385151461_thumb.png

per-pixel.bin

  • Like 3
Link to comment
Share on other sites

I think on ZX Spectrum they somehow managed to give you an impression of smooth scrolling by synchronizing the movements of low resolution "tiles" (attributes) with the refresh of the screen. I think it was a demo that used this. Simply a low resolution text based on attributes that scrolled smoothly from right to left. And for sure Spectrum does not have any sort of HW scroll and I believe it was not a bitmap shifting. It was just too fast to be that sort of thing. I will try to find it and post here.

Link to comment
Share on other sites

Another powerful method for scrolling is to use repeated copies of P0 and P1 together. While developing the Circus Atariage I did release a flickerless balloon test here showing smooth scrolling with 18 sprites per row. Ultimately it wasn't practical for the actual game since I still needed a sprite to draw the jumper, and not to mention the problem of masking balloons with the playfield. That is why Circus Atariage solely uses repeated copies of P1, and flickers between 2 frames to create the 18 sprites per row.

 

 

However, this method can still be very useful in certain situations. Here is another demo I started about a year ago. I haven't done much with it until this morning when I added some small updates to show y'all that the playfield is still free to use. :)

 

 

post-7074-0-64218300-1385321602_thumb.png

 

 

Simple Quest.zip

 

 

 

  • Like 5
Link to comment
Share on other sites

I think on ZX Spectrum they somehow managed to give you an impression of smooth scrolling by synchronizing the movements of low resolution "tiles" (attributes) with the refresh of the screen

That's automatic on the Atari 2600, because (usually, Boulder Dash a rare exception) you don't have a frame buffer which could create tearing when updated out of sync.

 

The scrolling looks smooth as long as the scrolling frame rate is high enough to fool the eyes (e.g. 30 Hz). The step size becomes quite irrelevant then. Small steps are only required for slow moving stuff.

Edited by Thomas Jentzsch
Link to comment
Share on other sites

That's automatic on the Atari 2600, because (usually, Boulder Dash a rare exception) you don't have a frame buffer which could create tearing when updated out of sync.

 

The scrolling looks smooth as long as the scrolling frame rate is high enough to fool the eyes (e.g. 30 Hz). The step size becomes quite irrelevant then. Small steps are only required for slow moving stuff.

 

I agree Tom. My ASDK scrolling demo for the Supercharger looks smooth at high speeds despite the large pixel increments:

 

ASDK_SuperCharger.bin

 

It's only smooth on the real hardware though; the tearing in Stella is happening for lack of double buffering without the glide wrappers (I have a framebuffer too :) ).

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...