Easing in/out for screen scrolling? (SOLVED)

Started by Ali, Thu 06/04/2006 17:25:05

Previous topic - Next topic

Ali

I felt that one of Syberia's best technical features was the smooth scrolling movement, the way it sped up and slowed down when following the player character.

The game I'm working on is 640x480 and I feel that implementing this sort of scrolling would make camera movement look nicer in my game.

I feel it's bad etiquette not to make an attempt to code this myself before asking for help, but I'm really not sure how I would go about it. Any thoughts on how I might approach this idea?

Wretched

Something like this maybe.
You can change the 0.1's to adjust the speed it follows the player.
You'll also probably need to write a initialization function for when a player enter a room.

Top of Global script
Code: ags

bool AutoScroll=true;
float AutoScrollX;
float AutoScrollY;


in function repeatedly_execute_always() , you might have to add this function to the global script as it's not there by default.
Code: ags

Ã,  if (AutoScroll)
Ã,  {
Ã,  Ã,  float X;
Ã,  Ã,  float Y;
Ã,  Ã,  X=IntToFloat(player.x)-160.0;
Ã,  Ã,  Y=IntToFloat(player.y)-120.0;
Ã,  Ã,  AutoScrollX=AutoScrollX+(X-AutoScrollX)*0.1;
Ã,  Ã,  AutoScrollY=AutoScrollY+(Y-AutoScrollY)*0.1;
Ã,  Ã,  
Ã,  Ã,  SetViewport(FloatToInt(AutoScrollX,eRoundNearest), FloatToInt(AutoScrollY,eRoundNearest));
Ã,  }
Ã, 

Kweepa

Here's some pseudocode.
Pseudocode because I just typed it off the top of my head and it has a couple of variables that you'll have to set up/apply yourself (characterX, screenCentre).

The idea is that you accelerate the screen scroll up to a maximum speed that decreases when close to the character.

Code: ags

float scrollSpeed = 0.0;
float screenCentre = 160.0;

// rep_ex

float targetScrollSpeed = 5.0; // pixels per second
float slowDownRange = 30.0; // pixels
float scrollOffset = IntToFloat(characterX) - screenCentre;
if (Abs(scrollOffset) < slowDownRange)
{
   targetScrollSpeed = (scrollOffset/slowDownRange)*targetScrollSpeed;
}
else
if (scrollOffset < 0.0)
{
   targetScrollSpeed = -1.0*targetScrollSpeed;
}
float timeStep = 1.0f/IntToFloat(GetGameSpeed());
scrollSpeed += timeStep*(targetScrollSpeed - scrollSpeed);
screenCentre += FloatToInt(timeStep*scrollSpeed);
// update the viewport here
Still waiting for Purity of the Surf II

Ali

Thanks guys, this is more than I expected!


I think I understand most of your code Steve, and my screens only scroll horizontally so It seems most useful. My maths isn't great though, so I could do with clarification on a couple of points:

Am I right in thinking I should set screenCentre to half the width of the room? Or should that be the current X position of the viewport?

Code: ags

float scrollSpeed = 0.0;
float screenCentre = 160.0;

// rep_ex

float targetScrollSpeed = 5.0; // pixels per second
float slowDownRange = 30.0; // pixels
float scrollOffset = IntToFloat(characterX) - screenCentre;
if (Abs(scrollOffset) < slowDownRange)
{
Ã,  Ã, targetScrollSpeed = (scrollOffset/slowDownRange)*targetScrollSpeed;
}

I think this segment decreases the targetScrollSpeed as scrollOffset enters the slowDown range of 30 pixels near to the player.

Code: ags

else
if (scrollOffset < 0.0)
{
Ã,  Ã, targetScrollSpeed = -1.0*targetScrollSpeed;
}

This passage will invert the targetScrollSpeed if the player is to the left of the screen center, I reckon.

Code: ags

float timeStep = 1.0f/IntToFloat(GetGameSpeed());
scrollSpeed += timeStep*(targetScrollSpeed - scrollSpeed);
screenCentre += FloatToInt(timeStep*scrollSpeed);
// update the viewport here


It's this crucial-looking bit I have trouble following I'm afraid. I guess I should use SetViewport, but which variable should I use to set the X position of the viewport?

Thanks again for your help guys!

Kweepa

Yup, screenCentre is the x position of the centre of the viewport.
Still waiting for Purity of the Surf II

Ali

#5
Ah, that explains why I was having trouble. I was setting screenCentre to the middle of my room. Aside from that I had trouble with this line:

Code: ags

screenCentre += FloatToInt(timeStep*scrollSpeed);
// update the viewport here


screenCentre is a floating point, so AGS won't give it an integer value. Sould I use something like this?

SetViewport (FloatToInt(screenCentre), 0);

Also, the editor didn't like the 'Abs' or '1.0f', but I couldn't tell if they were typos.

Sorry for asking so many questions, but my home computer is without internet so I can't try any of this out until later.

Thanks again!

-Al.

Kweepa

#6
Sounds good.
Code: ags

SetViewport(FloatToInt(screenCentre) - screenWidth/2, 0);

Use 1.0 instead of 1.0f (that's a C-ism).
And I see that AGS doesn't have an abs function. Dang.
Use
Code: ags

if (scrollOffset > -slowDownRange && scrollOffset < slowDownRange)

instead.
Still waiting for Purity of the Surf II

Ali

It works! It'll take a bit of tweaking to get the speed right but it works. Thanks so much Steve. In case anyone else ever wants to do this the code I used was like this:

Code: ags


// in the universal script header:

float scrollSpeed = 0.0;
float screenCentre = 160.0;

// in repeatedly_execute

float targetScrollSpeed = 5.0; // pixels per second
float slowDownRange = 30.0; // pixels
float scrollOffset = IntToFloat(characterX) - screenCentre;
if (scrollOffset > -slowDownRange && scrollOffset < slowDownRange)
{
   targetScrollSpeed = (scrollOffset/slowDownRange)*targetScrollSpeed;
}
else
if (scrollOffset < 0.0)
{
   targetScrollSpeed = -1.0*targetScrollSpeed;
}
float timeStep = 1.0/IntToFloat(GetGameSpeed());
scrollSpeed += timeStep*(targetScrollSpeed - scrollSpeed);
screenCentre += (timeStep*scrollSpeed);

SetViewport(FloatToInt(screenCentre) - screenWidth/2, 0);

SMF spam blocked by CleanTalk