Adjusting a background's size within the script?

Started by Feenyx, Wed 15/10/2014 20:39:11

Previous topic - Next topic

Feenyx

Hello everyone,

Here is the problem:

Some of my backgrounds imported into AGS 3.3.0 have black fills on both sides. And they show while playing, because the camera is centered on the main character. However, I do not want to change the camera, I only want to re-define the edges of my backgrounds manually for each room so that the camera doesn't show those black fills anymore.

Since I'm almost done with the scripting, I don't want to re-create each of my 50 backgrounds without the black fills because when I change a background on AGS, it resets all walkable areas, hotspots, regions, walk-behinds. Also, all of my cut scenes, objects and characters have to be repositioned. Which pretty much means I have to start all over again...

So my question is this:

Would it be possible to change the script for each room to define the backgrounds' edges so the camera doesn't show those black fills without having to re-create all of them and pretty much start over?

Here is an image of the problem, in game:



Here are the true edges of the background:



Is my question clear enough? :-[
I am in desperate need of help here! ???

Cassiebsg

AGS only resets that stuff, if you import a BG with a different resolution/size than the original one.
Are your BGs shorter than game resolution? I'm no expert, but if you import shorter BGs then AGS needs to fill in the space with something... otherwise it should just scroll until it can't no more with added black edges like those.

But maybe someone with more experience can give you a better reply and solution to the problem.
There are those who believe that life here began out there...

Feenyx

Quote from: Cassiebsg on Wed 15/10/2014 20:53:33
AGS only resets that stuff, if you import a BG with a different resolution/size than the original one.
Are your BGs shorter than game resolution? I'm no expert, but if you import shorter BGs then AGS needs to fill in the space with something... otherwise it should just scroll until it can't no more with added black edges like those.

They should have the same length but a shorter width if I was ever to remove the black fills from my BGs. So importing the new BGs would definitely reset the stuff showed in the room.

Snarky

Yes, it's possible, but given your other scripting questions, are you really that far along that it wouldn't be better to just reimport them?

I'm also wondering why you imported them with black bars in the first place, and why you didn't fix it right away when you noticed the problem.

Feenyx

Quote from: Snarky on Thu 16/10/2014 18:19:06
Yes, it's possible, but given your other scripting questions, are you really that far along that it wouldn't be better to just reimport them?

I'm also wondering why you imported them with black bars in the first place, and why you didn't fix it right away when you noticed the problem.

This is my first project on AGS and as for my other scripting question, I did not allow to open/close doors in the game back then as it was not a priority.
As for my background fills, I really did not urge to the problem before because I did not think that changing the sizes of my BGs would have been a problem.
But now I'm getting anxious to think that I might have to start all over again as I'm almost done with the scripting of a complete walkthrough, dialogues, cut scenes and changing all the positioning would take quite a while and create multiple issues if not processed correctly.

Cassiebsg

Wouldn't it then be better to change the camera when the character reaches "the critical" point in the BG, and move the camera so it never shows the black edge (maybe using a region)?
I'm no expert in coding, but it would probably be easier to add a few lines of code to each room, instead of having to redraw all the areas, and behinds and hotspots, an objects, if you are that far along.
There are those who believe that life here began out there...

Feenyx

Quote from: Cassiebsg on Thu 16/10/2014 20:04:17
Wouldn't it then be better to change the camera when the character reaches "the critical" point in the BG, and move the camera so it never shows the black edge (maybe using a region)?
I'm no expert in coding, but it would probably be easier to add a few lines of code to each room, instead of having to redraw all the areas, and behinds and hotspots, an objects, if you are that far along.


Like you said, it would be easier for me to add a few lines of code to each room. Using regions would be a lot of trouble but doable. I'll just wait and see what Snarky has to say about that, first.

Thanks

Snarky

If all the screens have equally wide black bars, do this:

Code: AGS

#define SIDEBAR_WIDTH 32 // or whatever

function repeatedly_execute_always()
{
  // Other stuff ...
  viewportX = player.X - System.ViewportWidth/2;
  viewportY = player.Y - System.VewportHeight/2;
  if(viewportX < SIDEBAR_WIDTH) viewportX = SIDEBAR_WIDTH;
  else if(viewportX + System.ViewportWidth >= Room.Width - SIDEBAR_WIDTH) viewportX = Room.Width - SIDEBAR_WIDTH - 1;
  Room.SetViewport(viewportX, viewportY);
  // Other stuff ...
}


Untested, but I think that's the gist of it. If different rooms have different black bars, I would create a custom room property to store the width of the bar, and use that in the calculation instead of SIDEBAR_WIDTH.

Feenyx

Quote from: Snarky on Thu 16/10/2014 21:38:24
If all the screens have equally wide black bars, do this:

Code: AGS

#define SIDEBAR_WIDTH 32 // or whatever

function repeatedly_execute_always()
{
  // Other stuff ...
  viewportX = player.X - System.ViewportWidth/2;
  viewportY = player.Y - System.VewportHeight/2;
  if(viewportX < SIDEBAR_WIDTH) viewportX = SIDEBAR_WIDTH;
  else if(viewportX + System.ViewportWidth >= Room.Width - SIDEBAR_WIDTH) viewportX = Room.Width - SIDEBAR_WIDTH - 1;
  Room.SetViewport(viewportX, viewportY);
  // Other stuff ...
}


Untested, but I think that's the gist of it. If different rooms have different black bars, I would create a custom room property to store the width of the bar, and use that in the calculation instead of SIDEBAR_WIDTH.

Okay, first, they all are of different Width and second, what do I have to change lets say my background here is 95 X (black filled from 0 to 95)?

Snarky

#9
Gosh, you've really screwed yourself on this one, haven't you? Do I take it the bars aren't necessarily the same width on each side of the image, either?

Like I said, create a custom room property (look it up in the manual; you want type int and default 0), or in this case two properties, and call them something like "SidebarLeft" and "SidebarRight". Set them to the correct values for each room.

Then replace SIDEBAR_WIDTH with the respective room property, like so:

Code: AGS
  if(viewportX < GetRoomProperty("SidebarLeft")) viewportX = GetRoomProperty("SidebarLeft");
  else if(viewportX + System.ViewportWidth >= Room.Width - GetRoomProperty("SidebarRight")) viewportX = Room.Width - GetRoomProperty("SidebarRight") - 1;


You put this in the global script, and it should work for every room where you've set the custom property values.

Edit: This is based on the 3.2.1 documentation. I seem to remember that in 3.3, GetRoomProperty() is now Room.GetProperty(), for consistency.

Feenyx

Quote from: Snarky on Fri 17/10/2014 16:52:13
Gosh, you've really screwed yourself on this one, haven't you? Do I take it the bars aren't necessarily the same width on each side of the image, either?

Like I said, create a custom room property (look it up in the manual; you want type int and default 0), or in this case two properties, and call them something like "SidebarLeft" and "SidebarRight". Set them to the correct values for each room.

Then replace SIDEBAR_WIDTH with the respective room property, like so:

Code: AGS
  if(viewportX < GetRoomProperty("SidebarLeft")) viewportX = GetRoomProperty("SidebarLeft");
  else if(viewportX + System.ViewportWidth >= Room.Width - GetRoomProperty("SidebarRight")) viewportX = Room.Width - GetRoomProperty("SidebarRight") - 1;


You put this in the global script, and it should work for every room where you've set the custom property values.

Okay, I got ya but now it says that the viewportX is an undefined symbol?

Snarky

#11
Yes because I forgot to declare it as an int first:

Code: ags
  int viewportX = player.X - System.ViewportWidth/2;
  int viewportY = player.Y - System.VewportHeight/2;


For stuff like this, your best bet is going through the scripting tutorial in the manual.

Feenyx

When I'm adding a new custom room property, there is no "int" Type. There's only Boolean, Number and Text. I selected Number for now but I'm guessing that wont work since it's not an "int"?

Cassiebsg

There are those who believe that life here began out there...

Crimson Wizard

Quote from: Snarky on Fri 17/10/2014 16:52:13
Edit: This is based on the 3.2.1 documentation. I seem to remember that in 3.3, GetRoomProperty() is now Room.GetProperty(), for consistency.
Not in 3.3, since 3.4 alpha.


int - is short for integer.

Feenyx

Quote from: Crimson Wizard on Fri 17/10/2014 21:23:21
Quote from: Snarky on Fri 17/10/2014 16:52:13
Edit: This is based on the 3.2.1 documentation. I seem to remember that in 3.3, GetRoomProperty() is now Room.GetProperty(), for consistency.
Not in 3.3, since 3.4 alpha.


int - is short for integer.

Its true, I's using currently using 3.3. I'll check this out and let you know what happens. Thanks.

Feenyx

Quote from: Crimson Wizard on Fri 17/10/2014 21:23:21
Quote from: Snarky on Fri 17/10/2014 16:52:13
Edit: This is based on the 3.2.1 documentation. I seem to remember that in 3.3, GetRoomProperty() is now Room.GetProperty(), for consistency.
Not in 3.3, since 3.4 alpha.


int - is short for integer.

Well I've tried to change GetRoomProperty to Room.GetProperty but it says ".GetProperty" is not a public member of "Room". So I'm guessing Crimson's right.

So how can I adjust all this to work? It still isn't working. My custom room properties can't be an "int". So I tried with "Number" and no error message shows, but it still isn't working.

Snarky

Please be more specific than "still isn't working."

Once you've fixed typos and stuff like that it should have worked for the left-hand side. There was an error in the calculation of the right-hand side (I forgot to take into account the width of the screen) that meant it would ALWAYS show the right sidebar if the character was on the right-hand side of the screen: that would be a useful thing to report.

I've tested it with this code, and it's working for me (AGS 3.3):

Code: ags
function repeatedly_execute_always()
{
  // Scroll viewport so player is at the center of the screen (default behavior)
  int viewportX = player.x - System.ViewportWidth/2;
  int viewportY = player.y - System.ViewportHeight/2;
  // Don't scroll into left sidebar
  if(viewportX < GetRoomProperty("SidebarLeft"))
    viewportX = GetRoomProperty("SidebarLeft");
  // Don't scroll into right sidebar
  else if(viewportX + System.ViewportWidth >= Room.Width - GetRoomProperty("SidebarRight"))
    viewportX = Room.Width - System.ViewportWidth - GetRoomProperty("SidebarRight");

  SetViewport(viewportX, viewportY);
}


If not, have you remembered to set the actual values of those two properties? Are you sure the names match exactly, capitalization and all?

Feenyx

#18
Quote from: Snarky on Sat 18/10/2014 20:31:19
Please be more specific than "still isn't working."

Once you've fixed typos and stuff like that it should have worked for the left-hand side. There was an error in the calculation of the right-hand side (I forgot to take into account the width of the screen) that meant it would ALWAYS show the right sidebar if the character was on the right-hand side of the screen: that would be a useful thing to report.

I've tested it with this code, and it's working for me (AGS 3.3):

Code: ags
function repeatedly_execute_always()
{
  // Scroll viewport so player is at the center of the screen (default behavior)
  int viewportX = player.x - System.ViewportWidth/2;
  int viewportY = player.y - System.ViewportHeight/2;
  // Don't scroll into left sidebar
  if(viewportX < GetRoomProperty("SidebarLeft"))
    viewportX = GetRoomProperty("SidebarLeft");
  // Don't scroll into right sidebar
  else if(viewportX + System.ViewportWidth >= Room.Width - GetRoomProperty("SidebarRight"))
    viewportX = Room.Width - System.ViewportWidth - GetRoomProperty("SidebarRight");

  SetViewport(viewportX, viewportY);
}


If not, have you remembered to set the actual values of those two properties? Are you sure the names match exactly, capitalization and all?

I've just tried your codes and it seems to work but when I'm walking away from the left side of the screen, the camera doesn't refocus onto the main character so I can't really test the right side bar.

Snarky

Can't reproduce: for me the screen scrolls to follow the character. What values do you have for the sidebars? (Note that if for example your right-hand sidebar is 50 pixels wide on a 900-pixel wide background, the SidebarRight value should be 50, not 850.)

Feenyx

Quote from: Snarky on Sat 18/10/2014 21:09:49
Can't reproduce: for me the screen scrolls to follow the character. What values do you have for the sidebars? (Note that if for example your right-hand sidebar is 50 pixels wide on a 900-pixel wide background, the SidebarRight value should be 50, not 850.)


Ugh, my bad. Got that fixed now. However, one last thing is the character seems to flicker like crazy, as much as the repeatable execute function occurs. Won't that affect my walk animation? (currently not animated)

Snarky

#21
Hmmyes, I see what you mean. It's a bug/limitation of SetViewport(), it only updates the viewport one frame after the character position is updated, so the character flickers between two positions on the screen. There is a workaround that might fix this (see here), but it gets a bit complicated. I'll see if I can add it in...

Edit: Try this. Since the code was getting mildly complicated, I broke it out into a separate function.

Code: AGS
// GlobalScript.asc
int animationCounter=0;
int animationFrameOld;

void scrollWithBoundaries()
{
  animationCounter++;
  if(animationFrameOld != player.Frame)
    animationCounter=0;
  if(animationCounter == player.AnimationSpeed || !player.MovementLinkedToAnimation)
  {
    // Scroll viewport so player is at the center of the screen (default behavior)
    int viewportX = player.x - System.ViewportWidth/2;
    int viewportY = player.y - System.ViewportHeight/2;
    // Don't scroll into left sidebar
    if(viewportX < GetRoomProperty("SidebarLeft"))
      viewportX = GetRoomProperty("SidebarLeft");
    // Don't scroll into right sidebar
    else if(viewportX + System.ViewportWidth >= Room.Width - GetRoomProperty("SidebarRight"))
      viewportX = Room.Width - System.ViewportWidth - GetRoomProperty("SidebarRight");

    SetViewport(viewportX, viewportY);
  }
  animationFrameOld = player.Frame;
}

function repeatedly_execute_always()
{
  scrollWithBoundaries();
}

Feenyx

Quote from: Snarky on Sat 18/10/2014 21:30:34
Hmmyes, I see what you mean. It's a bug/limitation of SetViewport(), it only updates the viewport one frame after the character position is updated, so the character flickers between two positions on the screen. There is a workaround that might fix this (see here), but it gets a bit complicated. I'll see if I can add it in...

Edit: Try this. Since the code was getting mildly complicated, I broke it out into a separate function.

Code: AGS
// GlobalScript.asc
int animationCounter=0;
int animationFrameOld;

void scrollWithBoundaries()
{
  animationCounter++;
  if(animationFrameOld != player.Frame)
    animationCounter=0;
  if(animationCounter == player.AnimationSpeed || !player.MovementLinkedToAnimation)
  {
    // Scroll viewport so player is at the center of the screen (default behavior)
    int viewportX = player.x - System.ViewportWidth/2;
    int viewportY = player.y - System.ViewportHeight/2;
    // Don't scroll into left sidebar
    if(viewportX < GetRoomProperty("SidebarLeft"))
      viewportX = GetRoomProperty("SidebarLeft");
    // Don't scroll into right sidebar
    else if(viewportX + System.ViewportWidth >= Room.Width - GetRoomProperty("SidebarRight"))
      viewportX = Room.Width - System.ViewportWidth - GetRoomProperty("SidebarRight");

    SetViewport(viewportX, viewportY);
  }
  animationFrameOld = player.Frame;
}

function repeatedly_execute_always()
{
  scrollWithBoundaries();
}


I tried this out and placed it on top of all my Global scripts functions. However, I think I might have placed it in the wrong place since it won't seem to work anymore. The camera just keeps following the main character at all times and still shows the black bars but no flickers. As if it was not considering it as a function since I removed it from the repeatable execute always section (which now contains scrollWithBoundaries). Also, I'm not getting any error messages. What did I do wrong?:~(

Snarky

I don't know, dude. When I first tested it I had the same problem, and my mistake was that I'd forgotten to actually call scrollWithBoundaries() in repeatedly_execute_always(), but if you ARE doing that...

Wait, you say "placed it on top of all my Global scripts functions"? There's only one copy, right? You haven't ended up with two separate repeatedly_execute_always() functions, for example?

If you can't get it to work, you could post or send me the contents of your global script.

SMF spam blocked by CleanTalk