I'm working on an rpg game, and one of the big issues that I had (have), is having the players actions change around other objects.

For example, normally the "a" key would attack, but when next to a person, it would trigger a dialog sequence, and when next to a rock, allow you to push/pull it around.

At first I thought to do something like this:

if(nextToPerson()) aCommand = talk;
else if(nextToRock()) aCommand = pushPull;
else aCommand = attack;

I then realized that this would be very inefficient in the long run, and cause the player class to be much larger than need-be.

I then came up with the idea of the surrounding objects controlling the players available actions.

example:

public interface ACommand{
    int aRange(); // how far does the action effect?
    void callACommand(/*args*/);
}

//========================

public class Person implements ACommand{
    // Player's a command changes within 1 meter of a person
    int aRange(){ return 1; } 
    void callACommand(/*args*/){ Player.talk(this); }
}

//========================

public class Player implements ACommand{ // default command
    int aRange(){ return 150; } // default value (may be something else)
    void callACommand(/*args*/){ Player.attack(); }
    void keyPressed(KeyEvent e){
        if(e.getKeyChar()=='a'){
            Object closestActionChange = null;
            if(closestActionChange = findClosestAction()){
                if(closestActionChange instanceof Player) 
                    this.callACommand();
                if(closestActionChange instanceof Person) 
                    ((Person)(closestActionChange)).callACommand();
            }
        }
   }
}

This is the solution that I came up with. It allows the Player class to remain somewhat simpler, and allows objects to govern themselves. findClosestAction() talks to the game engine to see what is around that can influence the Player's available actions. This is just something that I came up with, trying to make a game work a bit smoother. Most times, the interface would be implemented by the abstract super class of the object, and be overridden as necessary.

If you have any comments/suggestions, please let me know. I'm hoping that this is a good way to do this, and if not, I would like to know why, and where it could be improved. (This isn't really a question, rather a discussion about pros and cons of this way of doing things.)

Also, this is just a rough outline. The interfaces would be more structured, and things would fit together better than in the example. The keyPressed method in the player class would be better structured as well.

Edit:
Now, I'm thinking that the keyPressed method should go in the GameEngine class, which would hold the window, rather than in the player class

It sounds more logical the way you have it - for example, to have the game class keep a list of what Objects are currently showing on screen, then when the player wants to attack, you can call getClosestObject() or something of that nature to decide how the a button will work. But keep in mind that from what you're suggesting, the Player class will still have to switch (or use a bunch of if statements) on the type of Object that getClosestObject() returns.

True, but it significantly cuts down the size of the class, and spreads out the bulk of the code between other classes. And if the class abstraction is done well, it would simplify it even more.

Also, I just thought of this - If each game object stems from a class, GameObject, which would implement all the interfaces, it would only take a few lines of code in the Player class.
The abstract GameObject class would be similar to the Java Object class in nature - providing a base for everything in the game. It would implement all the interfaces that would influence the player, but not have anything in the method body (or something to signify that no actions are changed). There would then have to be an "boolean influencesPlayer()" method to see if subclassed GameObject changes the players actions, and base the actions available to the player off of those 2 methods. Since the things in game that could influence the Player all stem from GameObject, it would be possible to call <GameObject_instance>.callACommand(). Because each sub-class of GameObject has the option of overriding each implemented method, it allows that call to execute the farthest down overridden method in the hierarchy. I think that makes sense, I saw typing fast, and thinking as I went XD. I think it adds even more structure to the original idea.

Thanks for the comment! I love getting advise from people, because when I do, it makes me think about what they said, and what they suggested, and ways to incorporate that into my design. This should shorten the Player class even more - the point that you referred to.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.