Screen Transition[SOLVED]

Started by Vincent, Tue 26/09/2017 15:54:20

Previous topic - Next topic

Vincent

Good evening to all AGSer!

I'd like to ask to some of you how to make a custom screen transition properly.
More specifically, a screen transition how it's showed in this video.
The example is shown when the video reaches 4 minutes and 37 seconds (more or less).
https://www.youtube.com/watch?v=XksUf7DOHWE

At the top of my head, I image this is like the background was split halfway to separate the center of the image. So to have a left and right sides of the background separated. Then move them to the corresponding edge of the screen, so the left side moves to the left edge and vice versa for the right side. So it is like an "opened window" transition of the screen. But I am not pretty sure how to do this properly? (roll)
Could anyone give me some good advice on how to do this so far?

Crimson Wizard

Save a copy of background in previous room into dynamic sprite, in the new room create 2 dynamic sprites from its halves (left and right) and assign to two objects, or GUIs, or GUI buttons which are moved in opposite directions.

Vincent

Hello Crimson Wizard, thanks for the quick response.
What you say make sense. I am going to try out this workaround, hopefully to make it work well.


Vincent

#3
Okay, somehow I managed to make it work but not as I wish (by using Dynamic Sprite and Create from Screenshot).
When I do that my objects (oLeftSide and oRightSide) take the graphic from the screenshot just done, but then suddenly their graphics become all black? It is something that I am doing wrong of course.
Later I have edit the background graphic to Gimp so to save as image the left and the right side of the background.
I have imported the graphics and place them into my objects properly and then I have done something like this on script:

// main global script file
Code: ags

function ScreenTransition()
{
  if (object[0].X > -Room.LeftEdge) return;
  object[0].X-=7;
  if (object[1].X < -Room.RightEdge) return;
  object[1].X+=7;
  
  if (object[1].X >= Room.RightEdge && object[0].X <= Room.LeftEdge) trans = false;
}

function repeatedly_execute() 
{
  if (trans)
  {
    ScreenTransition();
  }
}



// room 1 script file
Code: ags

function hHotspot1_Interact()
{
  player.ChangeRoom(2);
}



// room 2 script file (the objects graphics here are already set to be the left and right side from the room background 1, so when the player change room to here it is showed the two objects with the graphics of the previous background)
Code: ags

function room_Load()
{
  trans = true;
}


It is working very well but I really would like to avoid this method because I don't want to edit each background anytime as left and right side separately and then to import them as I have done here.
I would like to do that directly in AGS, but somehow I am having hard times.

Crimson Wizard

#4
Declare three global DynamicSprite variables:
GlobalScript.ash
Code: ags

DynamicSprite *PreviousRoomScreen;
DynamicSprite *RoomTransitionLeft;
DynamicSprite *RoomTransitionRight;


Transition sprites will always be of same size, so you can create them in game_start:
Code: ags

    RoomTransitionLeft = DynamicSprite.Create(System.ViewportWidth / 2, System.ViewportHeight);
    RoomTransitionRight = DynamicSprite.Create(System.ViewportWidth / 2, System.ViewportHeight);


Write a function that creates this sprite from the room:
Code: ags

void SaveRoomScreen()
{
    if (PreviousRoomScreen)
        PreviousRoomScreen.Delete(); // delete previous one, if there was any
    // If you want to have only room background:
    PreviousRoomScreen = DynamicSprite.CreateFromBackground();
    // If you want to have full screenshot
    PreviousRoomScreen = DynamicSprite.CreateFromScreenShot();
}

You should be calling this function in every room's OnLeave event.


Then, a function that applies this saved screen to two objects. Although, I would really recommend using GUI or GUI buttons, because you will reuse same for any room, and with objects you must create these in every room you want such transition.
Code: ags

void AssignRoomScreen(Object* o_left, Object *o_right)
{
    if (PreviousRoomScreen == null)
        return; // no screen saved (yet?)

    // First draw parts of previous room screen upon the two transition sprites.
    DrawingSurface *ds = RoomTransitionLeft.GetDrawingSurface();
    ds.DrawImage(PreviousRoomScreen.Graphic, 0, 0);
    ds.Release();
    DrawingSurface *ds = RoomTransitionRight.GetDrawingSurface();
    ds.DrawImage(PreviousRoomScreen.Graphic, -System.ViewportWidth / 2, 0);
    ds.Release();

    // Now assign these sprites to objects:
    o_left.Graphic = RoomTransitionLeft.Graphic;
    o_right.Graphic = RoomTransitionRight.Graphic;
}

You should be calling this function in every room's OnLoad event.


The rest is just moving those objects. If you want non-blocking transition, you move them in repeatedly_execute, as you did, but if you want blocking, then probably AfterFadeIn is better.

Vincent

#5
Crimson Wizard, first of all, I would like to thank you very much as usual!
Secondly, the way I was making this before was totally wrong and that's the reason why I couldn't get it to work well. However, this is what I have done now (I had to make some minor changes because there was something wrong):

Code: ags

// main global script file

function game_start() 
{
  RoomTransitionLeft = DynamicSprite.Create(System.ViewportWidth / 2, System.ViewportHeight);
  RoomTransitionRight = DynamicSprite.Create(System.ViewportWidth / 2, System.ViewportHeight);
}

void SaveRoomScreen()
{
  if (PreviousRoomScreen)
  PreviousRoomScreen.Delete(); // delete previous one, if there was any
  PreviousRoomScreen = DynamicSprite.CreateFromBackground();
}


void AssignRoomScreen(Object* o_left, Object *o_right)
{
  if (PreviousRoomScreen == null) return; // no screen saved (yet?)
  // First draw parts of previous room screen upon the two transition sprites.
  DrawingSurface *ds = RoomTransitionLeft.GetDrawingSurface();
  ds.DrawImage(0, 0, PreviousRoomScreen.Graphic); //here
  ds.Release();
  DrawingSurface *dss = RoomTransitionRight.GetDrawingSurface();
  dss.DrawImage(-160, 0, PreviousRoomScreen.Graphic); //here (I could not get it to work by doing "-System.ViewportWidth" for some strange reason?
  dss.Release();
 
  // Now assign these sprites to objects:
  o_left.Graphic = RoomTransitionLeft.Graphic;
  o_right.Graphic = RoomTransitionRight.Graphic;
}


function ScreenTransition()
{
  if (object[0].X > -Room.LeftEdge) return;
  object[0].X-=7;
  if (object[1].X < -Room.RightEdge) return;
  object[1].X+=7;
  
  if (object[1].X >= Room.RightEdge &&
      object[0].X <= Room.LeftEdge) trans = false;
}

function repeatedly_execute() 
{
  if (trans)
  {
    ScreenTransition();
  }
}



// room script 1
Code: ags

function room_Load()
{
  SaveRoomScreen();
}

function hHotspot1_Interact()
{
  player.ChangeRoom(2);
}



// room script 2
Code: ags

function room_Load()
{
  AssignRoomScreen(oLeftSide, oRightSide);
  trans = true;
}


And, HOLY HELL!!! :-D
This is working perfectly now as I wished, thank you very much! :)

Regarding your suggestion to use GUI or GUI BUTTONS is totally fine, Although I could create a template of the room with those objects set in place. I am truly happy now that this is working very well and of course I don't need to edit the background with some program and to import them as sprites.

Still best regards as usual Crimson Wizard!

Crimson Wizard

Quote from: Vincent on Tue 26/09/2017 21:46:48
  dss.DrawImage(-160, 0, PreviousRoomScreen.Graphic); //here (I could not get it to work by doing "-System.ViewportWidth" for some strange reason?

There was a mistake in the code, you need to use "-System.ViewportWidth / 2", that's half of the screen width.

Vincent

#7
Jesus, you are right. (facepalm) Thanks once again for the hint ! :-[

SMF spam blocked by CleanTalk