Walking from Room 1 to Room 2, is it possible to change start coordinates?

Started by multi007, Tue 22/11/2022 18:23:05

Previous topic - Next topic

multi007

If I put the player's landing coordinates on the 2nd room, lets say 240 x 350, does that mean wherever he exits from room 1, he will always land on that same spot in room 2?

Because what I want to happen is just like it does in the KQ games, if the player exits a room on the top of the page, the player appears at the top of the room 2.   If he exits the bottom, he appears on the bottom. 

Here's a hand drawn sketch of what I want.    A to A,  or B to B,  or C to C...

I dont want the player to land at the same spot regardless of where he exits...

https://i.imgur.com/v1mns3ol.jpg

Nahuel

Uhmm just throwing a simple idea why not define
In the header

#def ROOM_COORDS 2, 250, 120

And you can pass player.changeRoom(ROOM_COORDS);

For each room definition  you can have the same args
Life isn't a game. Let's develop a life-like-game.

eri0o

I think something like player.ChangeRoom(2, 32 /*x*/, player.y) should work, so you keep your y reference.

This way you fix the X position but makes the destination y position depend on the previous player y position.

Snarky

Guys, you're forgetting that AGS has this feature built in.

Quote from: multi007 on Tue 22/11/2022 18:23:05Because what I want to happen is just like it does in the KQ games, if the player exits a room on the top of the page, the player appears at the top of the room 2.  If he exits the bottom, he appears on the bottom.

That is exactly what Character.ChangeRoomAutoPosition(int RoomNumber) does. If the character exits along one edge, it'll appear at the corresponding position along the edge of the opposite side of the new room, just as in your drawing.

multi007

Quote from: Snarky on Tue 22/11/2022 18:51:24Guys, you're forgetting that AGS has this feature built in.

Quote from: multi007 on Tue 22/11/2022 18:23:05Because what I want to happen is just like it does in the KQ games, if the player exits a room on the top of the page, the player appears at the top of the room 2.  If he exits the bottom, he appears on the bottom.

That is exactly what Character.ChangeRoomAutoPosition(int RoomNumber) does. If the character exits along one edge, it'll appear at the corresponding position along the edge of the opposite side of the new room, just as in your drawing.

Perfect!  Thank you.  I was banging my head trying to do this for an hour. 

newwaveburritos

Oh, wow, I didn't know that either and I coded it myself the hard way.  Well, live and learn!

multi007

Ok -  so now when I leave room 1, I end up on room 2 but on the far right side of room 2. (i want to be on the left side of room 2 when I leave room 2).  Like this...




I used auto position as suggested in a prior thread.

But also, now when I leave room 2 (from the far right side, walking to the left side) the room goes to black.

Here are my rooms and scripts.






Here's a video of what's happening here. 



So what I want is for player to go to room 2, then back to room 1.  (Its easy im sure, but im so new i cant figure it out.)

Funny thing - I had it looping originally - player went from room 1, to hotspot, then the room changed back to room 1. But i fixed that.





Khris

Without the second parameter AGS will only put the character on the opposite side if the character is within 10 pixels of the room border.
Your hotspot is wider than that so you need something like
Code: ags
  player.ChangeRoomAutoPosition(2, 1050);

Please make sure to always carefully read the manual entries for the commands you use.

The fade to black at the end seems like AGS is looping between rooms 1 and 2, make sure you use the 2nd parameter to position the character outside the area that triggers the room change.


Edit: did a quick test and unfortunately things are going to get a bit more complicated.

1) changing the room and ending up on a region triggers its "walks onto" event, so you really need to make sure to either place the character outside or only change the room conditionally using more elaborate scripting to prevent looping

2) ChangeRoomAutoPosition is buggy apparently, the Tumbleweed template's 2nd room is twice as wide and Roger ended up halfway between the room's center and edge, suggesting that AGS uses the distance from the center to calculate the new position, not the distance from the edge.

Snarky

For this type of room transition I would use room edges rather than hotspots or regions. The ChangeRoomAutoPosition() bug is however a showstopper for this approach.

It should be possible to recreate its (correct) functionality in script, though, using on_event(eEventEnterRoomBeforeFadein). I'll see if I can whip up a module—unless Khris wants to beat me to it.

Snarky

OK, I put together a quick little module to provide the functionality that ChangeRoomAutoPosition is supposed to have.

Code: ags
//Header
#define NO_POSITION -1001

enum RoomEdge
{
  eRoomEdgeOpposite = -1,
  eRoomEdgeNone,
  
  eRoomEdgeTop, 
  eRoomEdgeBottom, 
  eRoomEdgeRight, 
  eRoomEdgeLeft
};

import void ChangeRoomEdge(this Character*, int room, RoomEdge edge=-1, int position=NO_POSITION);

Code: ags
// Script
RoomEdge newEdge;
int newPosition;
#define DISPLACE_EDGE 1

void ChangeRoomEdge(this Character*, int room, RoomEdge edge, int position)
{
  switch(edge)
  {
    case eRoomEdgeNone:
      this.ChangeRoom(room);
      return;
    case eRoomEdgeOpposite:
    {
      int minDist = this.y - Room.TopEdge;
      RoomEdge minEdge = eRoomEdgeBottom;
      int pos = this.x;
      
      int dist = Room.BottomEdge - this.y;
      if(dist<minDist)
      {
        minDist = dist;
        minEdge = eRoomEdgeTop;
        pos = this.x;
      }
      dist = this.x - Room.LeftEdge;
      if(dist <= minDist)
      {
        minDist = dist;
        minEdge = eRoomEdgeRight;
        pos = this.y;
      }
      dist = Room.RightEdge - this.x;
      if(dist < minDist)
      {
        minDist = dist;
        minEdge = eRoomEdgeLeft;
        pos = this.y;
      }
      edge = minEdge;
      if(position == NO_POSITION)
        position = pos;
      // Fallthrough to default
    }  
    default:
      newEdge = edge;
      newPosition = position;
      this.ChangeRoom(room);
      return;
  }
}

function on_event(EventType event, int data)
{
  if(event == eEventEnterRoomBeforeFadein)
  {
    if(newEdge != eRoomEdgeNone)
    {
      switch(newEdge)
      {
        case eRoomEdgeTop:
          player.y = Room.TopEdge + DISPLACE_EDGE;
          if(newPosition != NO_POSITION) player.x = newPosition;
          break;
        case eRoomEdgeBottom:
          player.y = Room.BottomEdge - DISPLACE_EDGE;
          if(newPosition != NO_POSITION) player.x = newPosition;
          break;
        case eRoomEdgeLeft:
          player.x = Room.LeftEdge + DISPLACE_EDGE;
          if(newPosition != NO_POSITION) player.y = newPosition;
          break;
        case eRoomEdgeRight:
          player.x = Room.RightEdge - DISPLACE_EDGE;
          if(newPosition != NO_POSITION) player.y = newPosition;
          break;
      }
      newEdge = eRoomEdgeNone;
      newPosition = NO_POSITION;
    }
  }
}

Note that it uses the Room edges (which can be configured in the Room Editor) to determine which edge of the room you are closest to, and also to position you in the new room.

The API is a little different from Character.ChangeRoomAutoPosition():

Code: ags
  player.ChangeRoomEdge(4); // Change to room 4, on the opposite edge of where you exit
  player.ChangeRoomEdge(4, eRoomEdgeTop); // Change to room 4, on the top edge (with current x)
  player.ChangeRoomEdge(4, eRoomEdgeLeft, 400); // Change to room 4, on the left edge with y=400

Unlike Character.ChangeRoomAutoPosition(), you don't have to be within 10 pixels of an edge for it to move you to the opposite edge in the new room: whichever edge you are closest to (or, if you're outside the edges, the one you're furthest outside) will be used as your "exit" edge, no matter where in the room you are. (In fact, the behavior of ChangeRoomAutoPosition() as described in the manual is undefined if you're not within 10 pixels of an edge; it's probably time to deprecate it.)

Oh, and only call this on player. Calling it on other characters will likely have unexpected effects.

Snarky

It occurs to me that it would be possible to extend the functionality to support having other characters change rooms in this way as well. However, unless there is actual demand for this feature, I don't think it's worth the effort to implement.

"But in outline..."
1. If you can assume that the room size and room edges of the target room match that of the current room (all relevant rooms follow the same overall layout), you can calculate the target coordinates in this room and send the character to them when calling ChangeRoom(). Done.

2. If you cannot make that assumption, you can do either (a) something like what Nahuel suggests, and store the necessary information in some global array, and again calculate the target coordinates when calling ChangeRoom(); or (b) When sending other characters to a different room using the edge method, add them to a stack along with exit edge/position info; when changing rooms, check the stack to see if there are any characters in the room that need to be positioned.
[close]

SMF spam blocked by CleanTalk