[Solved] Vertical background - how to stop the top being cut off.

Started by Duckbutcher, Sat 16/09/2017 16:49:41

Previous topic - Next topic

Duckbutcher

I have a vertical background early in my game. It's about 320/400 and the character emerges from a door approximately halfway down. AGS defaults to showing the immediate environment, approximately the middle 3rd of the background, ie centered around the character, but I want to show the top of the background upon entering the room, with the character appearing at the bottom. How can I make AGS display the entire background from the top?

I hope this makes sense.


Crimson Wizard

#1
Use SetViewport function to control "camera" movement; you can look it up in the manual.

For example:
Code: ags

SetViewport (0, 0);

will lock camera having its top-left corner aligned to room's 0,0 coordinates.

If you want to have camera moving at certain offset to playable character, then you have to update it in global repeatedly_execute function (or room's "repeatedly executed" event), for example:

Code: ags

function repeatedly_execute()
{
    SetViewport(player.x - 100, player.y - 100);
}

This will keep camera so that character will always be at the bottom-right quarter of the screen (unless room is not scrollable).

Similarily you may create other tricks, like camera following another character, make it move towards mouse cursor, and so on.

When you want to return to automatic camera following player, do ReleaseViewport();

Duckbutcher

The first part works great, thanks.

However using that second script in the rep ex doesn't seem to make any difference. I then decided to put it in a script called by the player walking to a region, which resulted in a jarring "jump cut" type effect. Is there any way to set the original setviewport command just at room load, and then have it immediately released so the background scrolls normally from then on?

Crimson Wizard

Quote from: Duckbutcher on Sat 16/09/2017 17:21:00
However using that second script in the rep ex doesn't seem to make any difference. I then decided to put it in a script called by the player walking to a region, which resulted in a jarring "jump cut" type effect. Is there any way to set the original setviewport command just at room load, and then have it immediately released so the background scrolls normally from then on?

If I understand correctly, you want camera just to scroll down to player after the fade-in?
If so, you may put following in "after fade-in" room event:

Code: ags

function room_AfterFadeIn()
{
    int y = 0;
    while (y >= player.y)
    {
        SetViewport(0, y);
        // play with thise numbers to find a suitable speed/smoothness
        y += 1;
        Wait(1);
    }
    ReleaseViewport();
}

Duckbutcher

Not quite, sorry. I'll try to explain!

I want the player to see the top of a vertical background, and then for the background to scroll normally after that.

Effectively, I want the player character standing at a door towards the middle of a vertically scrolling background, so that the player can see the top of the background image. This is taken care of by the "viewport" command you specified earlier, thanks! However after that I want to background to scroll downwards as normal when the player clicks below. Everything I've tried so far (including a "releaseviewport" command), results in a jump-cut rather than regular scrolling.

So I basically want the player to start at a place where the top of the background image is visible, but then be able to scroll downwards normally when clicking around the image.

Crimson Wizard

#5
ReleaseViewport will always produce that jump, because it changes camera position instantly. For that reason you need to animate camera scroll, similarily to how I shown in my second post's example script.

One thing that is different though, you want the scroll occur when player clicks somewhere? In that case you just have to move that scrolling script to a function which is called when this click occurs, whether that's just a random click anywhere on screen (from on_mouse_click), or hotspot click event.

Duckbutcher

OK, you're just going to have to assume I'm a moron who doesn't understand coding..! Sorry if this is frustrating.

The SetViewport command you first gave me centers the camera on the top of the background, check. I can see the top of the background image, the player is where I want him to be, it's all good.

From that point I want the background to behave like normal. The player can click below the starting point and go down a ladder. I want the background to scroll as normal, following the player character down that ladder to the bottom without a camera jump.

Once again, apologies if this seems like baby talk.





Crimson Wizard

#7
So, to clarify, do you want camera to always keep player character a bit at the bottom of the screen all time in this room, or you want it to accelerate and "catch up" with player as he moves and then continue as normal (having character in the center of screen)?

Duckbutcher

You want it to accelerate and "catch up" with player as he moves and then continue as normal (having character in the center of screen)?

This!

Crimson Wizard

#9
Oh ok :) Sorry for initial misunderstanding.

Basically, what you need to do is create a variable that tells that camera is offset, and then close viewport up to character step by step in rooms' "repeatedly execute" event:


Something like this:
Code: ags

bool moving_viewport;
int viewport_speed;

function room_Load()
{
    SetViewport(0, 0);
    moving_viewport = true;
    viewport_speed = 3; // adjust if needed
}

function room_RepExec()
{
    if (moving_viewport)
    {
        int y = GetViewportY();
        if (y + viewport_speed >= player.y)
        {
            moving_viewport = false;
            ReleaseViewport();
        }
        else
        {
            SetViewport(0, y + viewport_speed); 
        }
    }
}


This also may need some adjustments, because I don't immediately remember if viewport is normally centered at character's x/y, or at some offset to also take character's height into consideration. Something that needs to be tested out.

Duckbutcher

OK, can't get that to work. Where does the

bool moving_viewport;
int viewport_speed;

go? I've put it in the room script file. Does it need to go in a specific place?

Crimson Wizard

Quote from: Duckbutcher on Sat 16/09/2017 18:53:28
OK, can't get that to work. Where does the

bool moving_viewport;
int viewport_speed;

go? I've put it in the room script file. Does it need to go in a specific place?
Yes, should be enough to put them at the beginning of room script file, outside of any function.
What exactly is happening, are there compilation errors, or errors in game? Did you register the OnLoad and RepExec functions in the room events panel?

Duckbutcher

It throws up an error message:

An internal error has occurred. Please note down yada yada

Error: prepare script error -18. (no such function in script)
trying to run 'room_Afterfadein' (Room 12)

Here's what my room script looks like:

Code: ags

// room script file
bool moving_viewport;
int viewport_speed;
 
function room_Load()
{   gMaingui.Visible=false;
    gAction.Visible=false;
    SetViewport(0, 0);
    moving_viewport = true;
    viewport_speed = 3; // adjust if needed
}
 
function room_RepExec()
{
    if (moving_viewport)
    {
        int y = GetViewportY();
        if (y + viewport_speed >= player.y)
        {
            moving_viewport = false;
            ReleaseViewport();
        }
        else
        {
            SetViewport(0, y + viewport_speed); 
        }
    }
}



I'm going to bed now (It's 3am where I live), but thanks a lot for you help, let me know if you can see what I'm getting wrong!

Crimson Wizard

Quote from: Duckbutcher on Sat 16/09/2017 19:10:13
Error: prepare script error -18. (no such function in script)
trying to run 'room_Afterfadein' (Room 12)


This means that you have "room_Afterfadein" registered on Room's events panel but do not have it in script. Simply remove it from the panel.

Duckbutcher

#14
Hi Crimson, just thought I'd check in and let you know how I solved it in the end.

I ended up using two hotspots, one at the top of the ladder and one at the bottom, and sightly modifying the code you gave me so a downwards scroll is triggered when the player steps on the top of the ladder (which also switches off that hotspot and turns on the second one), and an upwards one triggered by the bottom hotspot (which turns off that hotspot and turns the first one back on). Thanks for all your help in the face of my amateurishness! Appreciated mate.

SMF spam blocked by CleanTalk