How to deal with returning to rooms as the story progresses.

Started by Tyshalle, Thu 21/11/2013 04:50:27

Previous topic - Next topic

Tyshalle

This is probably a pretty basic question, but I'm not sure of the most elegant way of handling this.

Basically my protagonist has an apartment that he will return to at various points in the story. Each time he returns, it will be under different circumstances, and I'd like for his response to be different and for the interactions with the room to be different each time he goes back. It's a linear adventure, not one in which you wander back and forth between locations while you try to figure out puzzles. So for instance, the first time he enters his house, he's by himself, and he's looking to get some stuff out of his place. The second time he enters his place, several hours will have past, and he'll be returning with a friend, and instead of simply retrieving stuff and then leaving, they'll be spending some time in the apartment working on things and talking and that sort of stuff. The third time he returns to his place, his roommate will be home and will confront him about something (the roommate was not home the first two times).

So basically, we have three very different interactions that go on with and within the same room, but the room itself is largely unchanged.

I'm trying to figure out the best way to handle this. As this is my first time using AGS, I have certain ideas on how to make this work, but they most likely won't be the most efficient or simple way to do it, so I'd like some thoughts.

For instance, I could simply use the same images and remake the room three different times, so that I'd have three identical rooms that simply handle the same. This would be very easy to handle from a programming standpoint, but it sounds awfully inefficient. Alternatively I was thinking that I could simply create a Global Variable that adds 1 each time something happens right before he's about to go back to his apartment, and then simply reuse the same room, and have every interaction within the room say if (variable == X) run interaction Y, etc. That seems doable enough, but it also seems like a pretty complicated and convoluted way of running the code.

I'm not sure if there are other, even simpler ways of handling this. Any thoughts or ideas? What have you done in the past when setting up this sort of stuff?

Ghost

You already name the two options- you should base your choice on the amount of changes to the room and the overall complexity.

Using several rooms will give you more control and "cleaner" (more readable) code. If there are many objects and hotspots that differ between room states, this is probably the better way, because you won't have to enter several responses to many interactive elements. Dublication is inefficient, yes, but sometimes it still worke best.

Using one room will keep everything nicely on one script. If there are few objects, and some of them remain the same between room changes, I'd prefer this option.

I suggest you create an enum of "states" to use in your script, though: This is better than just using a number- instead of
if (story_state == 1)
you can then use
if (story_state == eEnterWithFriend)
That really helps to keep things readable.

I had a somewhat similar situation in a game of mine where one object in a room would change often and significantly depending on the player's actions, and the object had separate parts that would also change- it was messy. I eventually made an enum of states, but kept the object in "one room", where is turned into a spaghetti code monster. Using "nodes" and an enum to keep track of them helped a bit.

monkey0506

After Ghost mentioned flying spaghetti monsters, I was about to recommend using a finite state machine, but that's probably overkill for your situation. You've described it as being entirely linear, so a simple global variable should be sufficient. You can't add custom enums in the Global Variables pane, but you could make it an int, or just use the import/export method manually. Using an int won't stop you from using it like a regular enum (just provide the actual enum definition in the global script header).

If your game grew more complex (entering the room more times; the gameplay becoming less linear) then you might want to look into other strategies, but that's probably your best bet for what you've described. ;)

Ghost

Quote from: monkey_05_06 on Thu 21/11/2013 08:34:18
I was about to recommend using a finite state machine,

Funny you say that, I was about to mention that module myself (laugh). But yes, for a linear progress through states, it would be a bit too much.

Knox

Quote from: Ghost on Thu 21/11/2013 05:28:10
Using "nodes" and an enum to keep track of them helped a bit.

I found this thread pretty helpful, but what do you mean by "nodes"?
--All that is necessary for evil to triumph is for good men to do nothing.

Ghost

Quote from: Knox on Thu 21/11/2013 15:13:28
what do you mean by "nodes"?

"Nodes" as certain points in the story. The start would be a node, the hero meeting his mentor another one. The idea is that between nodes a lot of puzzles can happen, even non-linear stuff, but once you arrive at the next node you know what inventory the character has, what he learned, and so on. A safe point in the story where you as the designer can change things knowing that the player will be able to make progress now.

Technically, whenever a cool cutscene in MI2 took place, you had hit a node (nod)

festilligambe

I think the global variable route would be the way to go if everything is identical, however if things change like a night/day cycle different rooms would work.  When writing your code you could run an "if" statement each time to check but a better way would be to code all the interactions that do not change first (like looking at a chair, or photograph..) and then make your first "if" statement with whatever variable you use and code the entire first one then your second if and code everything in there to keep it all separate that way you can keep adding each time the new interactions, if any overlap just copy and paste the code into the new section.
New to programing, old school to adventure games

Khris

I guess the decision pretty much comes down to how much common code there would be. If like 80% of the available interactions will remain more or less the same, use one room. If there are much more changes, use separate ones. Or use one room for mostly similar situations A and B, and a second one for later in the game, when things have changed more.

TheBitPriest

I hate to just say, "Me too," but I'm with taking the more "built-in" route.

When you're thinking about efficiency, I guess it really depends on what you need to do.  As Khris said, if 80% of the room is the same, then yes, visit the same room twice.  The easiest, built-in, "default AGS" way to implement multiple visits would be with global variables.  AGS has a nice global variable list that will allow you to keep your globals in one neat, organized place.  IMHO, this list, along with using a naming convention, eliminates most of the hazards of using them.  I have used a bool like g_bFirstVisit to do what you're talking about.  Another cheap AGS trick to learn is the DoOnlyOnce() function. This could get sloppy, but it really depends on what you need to do. 

But if the location is only conceptually the "apartment" with different objects, hotspots, characters, cutscenes, I would make multiple rooms.  It's going to be easier to test.  The rooms will be less complex with less of a chance for bugs.  Plus, it's more flexible.  You might want to change the lighting of the background for the time of day.   You might want to paint some of the objects from your "states" into the background, making them hotspots, rather than fiddling with placing them as objects, and hiding/unhiding them according to the "state."

If your masks get to be complex or if you'd rather not paint the same walkable area multiple times, CRM Tools can help. 

Again, I know this post is a little superfluous, but I just wanted to flesh out a few details on the previous thoughts -- especially since you said that you're new to AGS. 

-TBP

Paul Franzen

FWIW--in case you don't have enough feedback yet--I had a similar situation where I had the character vising the same scene at different parts of the game, under very different circumstances. I ended up using the variable method, but I wish I hadn't. 

The code became sort of a mess (partly because I was just inexperienced at the time and didn't comment properly), with so many if/then statements for each hotspot and having to account for whether certain objects are there or not based on where you are in the game. In hindsight it would've been less confusing for me if I'd just made separate rooms (Kitchen - Act I, Kitchen - Act II), and so on, so I didn't have to consider every possible scenario whenever I needed to add an event to that screen.
The Beard in the Mirror (formerly testgame) - Out now on Steam! http://store.steampowered.com/app/385840
Other games I've worked on: http://paulmfranzen.com/games/

Tyshalle

Yeah, thanks to everybody for the feedback on this. I think the 80% rule of thumb is what I'll likely be following, and so far using the global variables with comments to help keep things ans simple. I tried figuring out the enum stuff, but I couldn't quite figure out how to get it to work. I figure using an integer with a comment next to it is just as good for my purposes, though maybe once I get more experienced/comfortable scripting I'll switch.

Thanks again!

Khris

To use enums, put this in the header:
Code: ags
enum Act {
  Act_I,
  Act_II,
  Act_III
};


Now you can use Act_II instead of 2 in your code:
Code: ags
Act CurrentAct;

...

  CurrentAct = Act_I;

...

  CurrentAct++; // start next act

SMF spam blocked by CleanTalk