Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Screen "Scrolling"

Credits go to Ariesnl, gnolam, James Stanley, Kikaru, LennyLen, and Tobias Dammers for helping out!
This thread is locked; no one can reply to it. rss feed Print
 1   2 
Screen "Scrolling"
Simsimius
Member #6,017
July 2005

Well, here's the story.

I decided to make my first game that uses an area larger then the default game screen. Since I've never done this before, I got the basic game template I always use. So the game has a black background, and one sprite.

Because in order to create a larger area I defined the size of the virtual screen.

#include <allegro.h>

#define VIRTUAL_W 2400;
#define VIRTUAL_H 1800;

And in my movement code, I have this:

1void GetControls()
2 {
3 if(key[KEY_UP]) { if(ypos - speed < 0) ypos = 0; else ypos -= speed; }
4 if(key[KEY_DOWN]) { if(ypos + speed + sprite->h > SCREEN_H) ypos = SCREEN_H - sprite->h; else ypos += speed; }
5 /*
6 if(key[KEY_LEFT]) { if(xpos - speed < 0) xpos = 0; else xpos -= speed; }
7 if(key[KEY_RIGHT]) { if(xpos + speed + sprite->w > VIRTUAL_W) xpos = SCREEN_W - sprite->w; else xpos += speed; }
8 */
9 if(key[KEY_RIGHT]) {CPlayer1::move_right();}
10 if(key[KEY_LEFT]) {CPlayer1::move_left();}
11
12 }
13
14
15void CPlayer1::move_right() {
16if(xpos + speed + sprite->w > SCREEN_W) xpos = SCREEN_W - sprite->w; else xpos += speed;
17if(xpos == SCREEN_W - sprite->w) {scroll_screen(800, ypos);}
18//CPlayer1::animate();
19}
20void CPlayer1::move_left() {
21if(xpos - speed < 0) xpos = 0; else xpos -= speed;
22//CPlayer1::animate();
23}

I'm trying to get the current screen to go the next area (Normally, X=0. I want the X=800, which is the next area/screen).

Any help with what I'm doing wrong?

____
There's no place like 127.0.0.1

James Stanley
Member #7,275
May 2006
avatar

Can we see your scroll_screen function?

Simsimius
Member #6,017
July 2005

I'm using the Allegro scroll screen:

int scroll_screen(int x, int y);

Quote:

Attempts to scroll the hardware screen to display a different part of the virtual screen (initially it will be positioned at 0, 0, which is the top left corner). You can use this to move the screen display around in a large virtual screen space, or to page flip back and forth between two non-overlapping areas of the virtual screen. Note that to draw outside the original position in the screen bitmap you will have to alter the clipping rectangle with set_clip_rect().
Mode-X scrolling is reliable and will work on any card, other drivers may not work or not work reliably. See the platform-specific section of the docs for more information.

Allegro will handle any necessary vertical retrace synchronisation when scrolling the screen, so you don't need to call vsync() before it. This means that scroll_screen() has the same time delay effects as vsync().

Return value: Returns zero on success. Returns non-zero if the graphics driver can't handle hardware scrolling or the virtual screen is not large enough.

See also: set_gfx_mode, show_video_bitmap, request_scroll, request_video_bitmap.
Examples using this: exscroll.

So, any ideas on what I've done wrong?

EDIT: If you can't reply to this post, then PM me.

____
There's no place like 127.0.0.1

LennyLen
Member #5,313
December 2004
avatar

Well, since scroll_screen() can only be called in your code when (xpos == SCREEN_W - sprite->w), I'd be checking whether or not this expression is ever true.

Simsimius
Member #6,017
July 2005

Great idea!

I entered this code in the character class:

if(xpos == SCREEN_W - sprite->w) {TRACE("Xpos DOES equal SCREEN_W - sprite->w");}

and the output file does say "Xpos DOES equal SCREEN_W - sprite->w".

So it does turn out to be true.

I must be doing something wrong with the scroll_screen.

Any ideas?

____
There's no place like 127.0.0.1

LennyLen
Member #5,313
December 2004
avatar

Did you read the following part of the scroll_screen() section of the manual?

Quote:

Mode-X scrolling is reliable and will work on any card, other drivers may not work or not work reliably. See the platform-specific section of the docs for more information.

[edit]You should really be checking the return value as well.

Simsimius
Member #6,017
July 2005

Return value for what?

And I can't seem to find the relevant information in the docs about "Mode X".
Is there any code to find out if it works on my computer?

Sorry for asking too much, but I'm still a "beginner".

____
There's no place like 127.0.0.1

Ariesnl
Member #2,902
November 2002
avatar

Why don't you make a "camera" and draw everything according to your camera position ?
That way you can scroll easily and you won't be drawing anything that can't be seen

[one moment'I'll grab my code]

Perhaps one day we will find that the human factor is more complicated than space and time (Jean luc Picard)
Current project: [Star Trek Project ] Join if you want ;-)

gnolam
Member #2,030
March 2002
avatar

Mode X is an archaic DOS graphics mode.

Anyway, the usual way of doing scrolling is not by using virtual screen space and the *_scroll() functions, but by changing the position of objects you blit to the screen.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

LennyLen
Member #5,313
December 2004
avatar

Quote:

Return value for what?

The return value of the call to scroll_screen.

Try this:

if(xpos == SCREEN_W - sprite->w) {

    if (scroll_screen(800, ypos) != 0)
        allegro_message("scroll_screen() failed!\n");
        exit(-1);

}

Ariesnl
Member #2,902
November 2002
avatar

void TSprite::draw(int camx,int camy)
{
int DrawX=int(screenmid_x+(x-camx));
int DrawY=int(screenmid_y+(y-camy));
// only draw what we see
if ((image!=NULL)&&(DrawX+(image->Width()/2)>0)&&(DrawX-(image->Width()/2)<800)&&(DrawY+(image->Height()/2)>0)&& (DrawY-(image->Height()/2)<600))
   {
     image->BlitRotated(DrawX, DrawY,angle,opacity); 
   }
}

this is my sprite drawing code .. the camx,camy coords are the MIDDLE of your viewscreen so if there is a spaceship at (10500,600) and your camera is also at (10500,600) the spaceship will appear in the middle of your screen

and sprite coords are the middle of the sprite NOT top left... why ? easier to make the aiming and docking AI code ;)

Perhaps one day we will find that the human factor is more complicated than space and time (Jean luc Picard)
Current project: [Star Trek Project ] Join if you want ;-)

Simsimius
Member #6,017
July 2005

Quote:

gnolam
Anyway, the usual way of doing scrolling is not by using virtual screen space and the *_scroll() functions, but by changing the position of objects you blit to the screen.

I think I get what you mean, however, that would be more complicated then having everything written to the virtual screen, and just making the screen scroll.

Quote:

Ariesnl
Why don't you make a "camera" and draw everything according to your camera position ?
That way you can scroll easily and you won't be drawing anything that can't be seen

[one moment'I'll grab my code]

I think you might be on the same idea as gnolam. However, I'll have to wait and see.

EDIT:
LennyLen, thanks for the code. It said it failed.

EDIT2:
Ariesnl,
I don't fully understand your method.

And everyone:
Does anyone have any other suggestions for scrolling without Mode X that operate similar to Screen_scroll.

____
There's no place like 127.0.0.1

Ariesnl
Member #2,902
November 2002
avatar

look again ;)

Perhaps one day we will find that the human factor is more complicated than space and time (Jean luc Picard)
Current project: [Star Trek Project ] Join if you want ;-)

Simsimius
Member #6,017
July 2005

I saw it and edited my post.

But I don't fully understand that method. Would you be able to explain in more detail? Thanks.

EDIT: Hold on, I think I got it.

So, the screen remains the same, but you have camx and camy, which can be as large as whatever, and all characters, AI, etc. follow those set of co-ordinates?

____
There's no place like 127.0.0.1

Ariesnl
Member #2,902
November 2002
avatar

By the way I'm using Openlayer so some functions are diffrent.. However it is highly advised to use OpenLayer...

Quote:

So, the screen remains the same, but you have camx and camy, which can be as large as whatever, and all characters, AI, etc. follow those set of co-ordinates?

... In the oposite direction offcourse

Perhaps one day we will find that the human factor is more complicated than space and time (Jean luc Picard)
Current project: [Star Trek Project ] Join if you want ;-)

Simsimius
Member #6,017
July 2005

I think I can manage to get a similar method in Allegro.

But I have just wondered something about the initial scroll-screen function:
Was I meant to create a bitmap for the entire virtual screen? I think I had better test this.

____
There's no place like 127.0.0.1

Ariesnl
Member #2,902
November 2002
avatar

I don't know actually
I used this method even before I ever used allegro, it always works and you only draw what's on screen

Perhaps one day we will find that the human factor is more complicated than space and time (Jean luc Picard)
Current project: [Star Trek Project ] Join if you want ;-)

Simsimius
Member #6,017
July 2005

The more I think about the method, the more sense it makes.

Hopefully, this is what I plan to do:
Create camx and camy, with the 0,0 being -800, -600 and camy and camx ending at it's 800,600 (not the screens.)

Using this, all objects, code, etc. will be placed according to camx and camy.

The only thing I can't work out is how to scroll, BUT, I think that using x++ and y++ for camx and camy (for when the player moves) will work.

Btw, how do I "reward" people who helped me via the forum? I DO tick the box marked "The question has been answered to my satisfaction!", right?

____
There's no place like 127.0.0.1

LennyLen
Member #5,313
December 2004
avatar

Quote:

Was I meant to create a bitmap for the entire virtual screen?

Yes, definitely.

[edit]

Quote:

Btw, how do I "reward" people who helped me via the forum? I DO tick the box marked "The question has been answered to my satisfaction!", right?

See previous answer. ;)

Ariesnl
Member #2,902
November 2002
avatar

yes just camx++ will sctoll to the left (as the camera goes to the right) and so on

If you check the "question was answered..." you'll get a credit list

BTW what game are you making ?

Perhaps one day we will find that the human factor is more complicated than space and time (Jean luc Picard)
Current project: [Star Trek Project ] Join if you want ;-)

Simsimius
Member #6,017
July 2005

Lennylen:

Quote:

Quote:
Was I meant to create a bitmap for the entire virtual screen?
Yes, definitely.

How should I go around doing this (just to check if it works).

Ariesnl:
I'm not 100% sure, but I was thinking of a top-down game. Preferably a top-down shooter, but that depends (I've done a space shooter, very, very simple however). Top-down games don't need animations (and I still haven't been able to animate any sprites, and I even tried the forums, but it's no big deal).

____
There's no place like 127.0.0.1

LennyLen
Member #5,313
December 2004
avatar

Quote:

How should I go around doing this (just to check if it works).

Take a look at the exscroll.c example that came with Allegro. Actually, you should try running ex_scroll.exe, as if it doesn't work, then you'll know that hardware scrolling isn't available on your system.

Simsimius
Member #6,017
July 2005

I will.

Ariesnl:
What do I do if I want to have an object at, for example, the camY and CamX values of -100, 10?

How would I, for example, get the following primitive to be at a certain camC and camY point (I'm using the primitive to test it out)

circlefill(buffer, int x, int y, int radius, int color);

EDIT: This isn't easy. The code you supplied above doesn't seem too easy to understand.

EDIT:
I ran the app, it says

Quote:

Unable to set a 320x240 mode with 640x240 virtual dimensions

EDIT3:
Does anyone else have any more ideas?

____
There's no place like 127.0.0.1

Tobias Dammers
Member #2,604
August 2002
avatar

Simsimius: Even if the scrolling functions happen to work on your particular computer, I suggest you never touch them again. Seriously.
Scrolling is implemented in hardware, by creating a video bitmap larger than the actual screen, and adjusting the screen pointer to whatever position you want. The problem with this is that there is not a single virtual screen size that is guaranteed to work on any platform; in fact, you might find yourself in a situation where no virtual screen at all is available. And even if there is a virtual screen, you can't rely on the width and height. In 640x480, for example, one card might give you 1024 x 2048, another might do 2048 x 512, yet another might give you 640 x 3000.
The scrolling interface is pretty much a relic from the DOS age, to provide scrolling even when redrawing the entire screen every frame wasn't doable. This way, certain (clumsy) optimizations like the dirty rectangles algorithm are possible. Nowadays, though, an entire screen redraw is seldom an issue, so you might just as well forget that such a thing as a virtual screen exists.
The only appliances for off-screen video bitmaps today are:
- page flipping and triple buffering (2 or 3 video bitmaps)
- hardware-accelerated sprites
A "camera" or "view transform" is (in a simple 2d game, at least) nothing more than a pair of offsets by which you shift the entire scene. For example, if your old drawing code says:

draw_sprite(playerspr, screenbuffer, x, y);

the new code would say:

draw_sprite(playerspr, screenbuffer, x + scroll_x, y + scroll_y);

As long as you apply the same offset to all drawing operations, you achieve the same effect as hardware scrolling.
Note that this gives you an opportunity for optimization, since you only need to draw objects that are actually visible on screen (or at least partly).

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Simsimius
Member #6,017
July 2005

So, let me get this straight, the method I originally tried is not recommended, at least by you. ok.

Now, the code you showed me near the bottom looks promising.

So,

draw_sprite(playerspr, screenbuffer, x + scroll_x, y + scroll_y);

The value of scroll_x scroll_y should be the size of the area beyone the usual 800, 600?
So scroll_x could equal, 1600;
and scroll_y could equal, 1200?
And whenever the character walks to the edge of the screen, scroll_x and scroll_y decreases?

Correct?

EDIT: No, hang on, the above can't be right. Would it be possible to explain just a little. It seems simple, but I can't figure it out completely. I just can't think today >_<

____
There's no place like 127.0.0.1

 1   2 


Go to: