Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm planning out an adventure game, and can't figure out what's the right way to implement the behaviour of a level depending on state of story progression.

My single-player game features a huge world where the player has to interact with people in a town at various points in the game. However, depending on story progression, different things would be presented to the player, for e.g. the Guild Leader will change locations from the town square to various locations around the city; Doors would only unlock at certain times of the day after finishing a particular routine; Different cut-screen/trigger events happen only after a particular milestone has been reached.

I naively thought of using a switch{} statement initially to decide what the NPC should say or which he could be found at, and making quest objectives interact-able only after checking a global game_state variable's condition. But I realised I would quickly run into a lot of different game states and switch-cases in order to change the behaviour of an object. That switch statement would also be massively hard to debug, and I guess it might also be hard to use in a level editor.

So I thought, instead of having a single object with multiple states, maybe I should have multiple instances of the same object, with a single state. That way, if I use something like a level editor, I can put an instance of the NPC at all the different locations he could ever appear at, and also an instance for each conversation state he has. But that means there'll be a lot of inactive, invisible game objects floating around the level, which might be trouble for memory, or simply hard to see in a level editor, i don't know.

Or simply, make an identical, but separate level for each game state. This feels the cleanest and bug-free way to do things, but it feels like massive manual work making sure each version of the level is really identical to each other.

All my methods feel so inefficient, so to recap my question, is there a better or standardised way to implement behaviour of a level depending on state of story progression?

PS: I don't have a level editor yet - thinking of using something like JME SDK or making my own.

share|improve this question
add comment

3 Answers 3

up vote 7 down vote accepted

I think what you need in this case is the State Design Pattern. Instead of having multiple instances of each game object, create a single instance, but encapsulate its behavior in a separate class. Create multiple classes, one for each possible behavior, and give all classes the same interface. Associate one to your game object (the initial state) and, when conditions change (a milestone is reached, the time of the day passes, etc) you switch that object's state (i.e. associate it with a different object depending on your game logic) and update its properties if applicable.

One example of how a state interface would look like (completely made up - just to illustrate the level of control this scheme gives you):

interface NPCState {
    Scene whereAmI(NPC o);
    String saySomething(NPC o);
}

And two implementing classes:

class Busy implements NPCState {
    Scene whereAmI(NPC o) {
        return o.getWorkScene();
    }
    String saySomething(NPC o) {
        return "Can't talk now, I'm busy!";
    }
}

class Available implements NPCState {
    Scene whereAmI(NPC o) {
        return TAVERN;
    }
    String saySomething(NPC o) {
        String[] choices = o.getRandomChat();
        return choices[RANDOM.getInt(choices.length)];
    }
}

And switching states:

// The time of day passed from "afternoon" to "evening"
NPCState available = new Available();
for ( NPC o : list ) {
    Scene oldScene = o.state.whereAmI(o);
    o.state = available;
    Scene newScene = o.state.whereAmI(o);
    moveGameObject(o, oldScene, newScene);
    ...

Important NPCs may have their custom states, the state choosing logic may be more customizable, and you can have different states for different facets of the game (in this example, I used a single class to tell both location and chat, but you could separate them and do many combinations).

This works well with level editors too: you can have a simple combo box to switch the "global" state of a level, then add and reposition the game objects as you want them to appear in that state. The game engine would be responsible for only actually "adding" that object to the scene when it has the correct state - but its parameters would still be editable in an user-friendly way.

(Disclaimer: I have little real-world experience with game editors, so I can's say with confidence about how professional editors work; but my point about the State Pattern still holds, organizing your code this way should be clean, maintainable and not waste system resources.)

share|improve this answer
    
y'know, you could combine this State design pattern with the associative array I described. You could code the state objects as described here, and then choose between different state objects using an associative array as I suggested. –  jhocking Jun 1 '12 at 11:49
    
I agree, it's also good to separate the game from its engine, and hardcoding game logic strengthens the coupling between them (reducing the possibility of reuse). There's a tradeoff, though, since depending on the complexity of your intended behavior trying to "soft code" everything may result in unnecessary clutter. In this case, a mixed approach might be desirable (i.e. have a "generic" state transition logic, but allowing for custom code to be incorporated as well) –  mgibsonbr Jun 1 '12 at 12:21
    
So as I understand it, there is one-to-one mapping btwn NPCState and GameState. Then I wld put NPCs in an array and iterate thru it, assigning the new NPCState when a game state change is observed. The NPCState has to be capable of knowing how to handle every diff NPC that is sent to it, so essentially the NPCState contains the behaviour of all NPCs for a given state? I like that all the behaviours store cleanly in a single NPCState, which maps cleanly to game editor implementation, but it kinda makes the NPCState pretty huge. –  Cardin Jun 2 '12 at 3:05
    
Oh, I think I misunderstood ur ans. I changed it a bit to include observers. So it's one diff NPCState for every diff NPC, except the super generic ones like Crowd NPC which can share state. For each game state, the NPC will register itself and its NPCState with an Observer. Hence the Observer will know exactly which NPC is registered to change behavior at which game state, and simply iterate through them. And on the game editor side, the game editor just has to pass a signal to the Observer to change the state of the whole level. –  Cardin Jun 2 '12 at 3:29
1  
Yes, that's the idea! Important NPCs will have many states, and the state transition will depend mostly on the completed milestones. Generic NPCs might also react to milestones sometimes, and even have their chosen state dependent on an internal property (let's say all NPCs have a default initial state, and when you talk to one of them for the first time he introduces himself, then enter the normal state-switching cycle). –  mgibsonbr Jun 2 '12 at 3:44
show 1 more comment

What about using a observer pattern to look for milestone-changes? If a change happens, some class would recognize this and handle for example a change that has to be done to a npc.

Instead of the mentioned state design pattern I would use a strategy-pattern.

If a npc has n ways to interact with the character and m positions where he could be, there is a maximum of (m*n)+1 classes you have to design. Using the strategy-pattern you would end up with n+m+1 classes but these strategies could also be used by other npcs.

So there could be a class handling the milestones, and classes who observe this class and handle either npc or enemies or whatever should be changed. If the observers get updated they would decide if they have to change something to the instances they rule. The NPC class for example would, in the constructor, inform the NPC-Manager when he has to be updated and what has to be updated...

share|improve this answer
    
The Observer pattern seems interesting. I think it could cleanly leave all responsibilities with the NPC to register itself with the state observer. The Strategy pattern feels a lot like Unity Engine's Trigger and AI behaviours, which is used to share behavior btwn diff game objects (i think). It sounds feasible. I'm nt sure what's the pros/cons right now, but that Unity uses the same method too is somewhat reassuring haha.. –  Cardin Jun 2 '12 at 2:36
    
I just used these two patterns a few times so I'm not able to tell you about the cons :-/ But I think it is nice in case of single responsibility and the availability to test every strategy :) It might get confusing if your using a strategy in many different classes and you want to find every class which uses it. –  TOAOGG Jun 3 '12 at 14:03
add comment

The choices I would consider are either making the individual objects respond to different gamestates, or serve up different levels in different gamestates. The choice between those two would depend on what exactly I am trying to do in the game (what are the different states? how will the game transition between states? etc.)

Either way however I wouldn't do it by hard-coding the states into the game code. Rather than a massive switch statement in NPC objects, I would instead of the NPC behaviors loaded into an associative array from a data file and then use that associative array to run different behavior for their associated states, something like this:

if (state in behaviors) {
  behaviors[state]();
}
share|improve this answer
    
Would that data file be a kind of scripting language? I think a plain text data file might not be enough to describe behaviour. At any rate, you're right that it should be dynamically loaded. I can't quite think of using a game editor to generate valid Java code, it definitely have to be parsed somewhat. –  Cardin Jun 2 '12 at 2:23
1  
Well that was my initial thought, but after seeing mgibsonbr's answer I realized you could code the various bevaviors as separate classes and then in the data file just say which behavior classes go with which state. Load that data into an associative array at runtime. –  jhocking Jun 2 '12 at 15:51
    
Oh.. Yea that's definitely simpler! :D Compared to the scenario of embedding something like Lua haha.. –  Cardin Jun 3 '12 at 2:15
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.