aspose file tools*
The moose likes Game Development and the fly likes MVC for text adventure: working out how the classes interact Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Game Development
Bookmark "MVC for text adventure: working out how the classes interact" Watch "MVC for text adventure: working out how the classes interact" New topic
Author

MVC for text adventure: working out how the classes interact

Richard Henderson
Ranch Hand

Joined: Feb 18, 2013
Posts: 42
This is also for the game I was having GUI issues with. Those are mostly sorted now. I need to figure out how my classes will interact and how the game will run.

My Main class contains my main(String[] args) { method, of course.

This method instantiates an instance of my GUI, which is my view and contains labels to display the players characteristics and methods to update them as they play. The GUI class also displays a background image in the frame and a location image in a panel.

The main method also instantiates an instance of the Player class. This class contains the player's stats as variables and a number of methods for updating them and making random rolls based on those values. This class also contains instances of the weapons and armour the player uses, both of which are also classes.

The Player class extends the Creature class, as players and creatures share several stats and methods. No creatures are instantiated until the game is actually running though.

My first question is whether I should include "Fight" as it's own class or as a method of the Player class. I think it should be a method of Player as methods are supposed to represent behaviours, not 'things'. (If it's a method of Player then it will receive the Creatures instantiated by the location/game as arguments and access the Player's and the Creatures members this way.)

A more significant question now, about the best way to run the game:

Should I have a "Game" class which receives the instances of Player and GUI as arguments? The Game instance would then call methods like namePlayer(), rollPlayerStats(), chooseWeapon(), etc. Or could I just call those methods from the Main method and do away with the Game class? The Game class, or the main method would then be the Model and/or Controller.

After the player is fully defined the game will start properly. I imagine I will need an Area class which contains a title, description, monsters, treasure, etc. as parameters and these are instantiated as needed. At this point I am wondering if I will need to start a loop while(playerIsAlive) which calls a method to send the description to the output text area and ask for input (from a JOptionPane)?

Maybe something like this pseudo code:


I'm using an Enum to hold the values for the parameters of the different creature types. I could do the same thing with the details for the different areas. That seems preferable to constructing the areas through a long form. That way it will be easier to see the total number of creatures, items, treasure and experience points the player can get.

Am I coming at this from the right direction? Is there anything that I've overlooked? Any suggestions welcome.

Thanks in advance.
Piter Smith
Ranch Hand

Joined: Feb 25, 2009
Posts: 55
Richard Henderson wrote:
The main method also instantiates an instance of the Player class. This class contains the player's stats as variables and a number of methods for updating them and making random rolls based on those values. This class also contains instances of the weapons and armour the player uses, both of which are also classes.



As to weapons and armour, if the player has-a weapon then it's tightly coupled. I would suggest an inventory Collection, maybe two collections, not sure.

Perhaps a map of body part => equipment ?
and, perhaps, a list of carried items?

what happens when the player has a pack/sack/whatever and puts equipment into the sack.

In general, I would try not to put too much directly into the player.


Also, for text based games, while I have no direct experience, there is:



http://en.wikipedia.org/wiki/CoffeeMUD


which is a text based game engine written in Java. There's a similar effort in groovy, for what it's worth.


You could always find a game running CoffeeMUD and offer to code for them

you get to code, they get to improve their game, everyone wins.
Richard Henderson
Ranch Hand

Joined: Feb 18, 2013
Posts: 42
Thanks for your reply Piter. I was starting to think I'd have to make a few other threads, each covering only a very specific aspect of these issues. I will have to do that anyway for some things.

Yes, the Player has-a Weapon and the Player has-an Armour. Neither of those will actually be listed in the "Inventory", just as members of the Player class.

The inventory will be a List or Array, displayed in a JList component. This will represent the characters backpack and be limited to 10 or 12 items (Maybe stackable) The player will not be able to pick up other container items in this version of the game. I will be making the Inventory as a separate class then the Player will Have-an Inventory too.

Mapping Items to Locations is more sophisticated than I need to be in this game version too. If this works I'll go more detailed in a later version which might include items by location though. That later version will also be more graphical too and might head away from text based altogether. I'm intend to work my way up through the levels of complexity with each version.
Piter Smith
Ranch Hand

Joined: Feb 25, 2009
Posts: 55
Richard Henderson wrote:Yes, the Player has-a Weapon and the Player has-an Armour. Neither of those will actually be listed in the "Inventory", just as members of the Player class.

The inventory will be a List or Array, displayed in a JList component.



I'm suggesting that instead of the player having reference to one, or several Weapon objects, and then one or several Armour objects, that all equipment should be in a Collection(s).


class Player

Map<BodyPart,Armour> armours;
Map<HandFoot,Weapon> weapons;
List<Equipment> equip;

unless maybe some armour can be a weapon as well?

so, maybe just

Map<BodyPart,Equipment> worn;
List<Equipment> carried;

so that you don't lock yourself in and limit character design...?

when it comes time for swing, it's easy enough to to populate a Jlist...
Piter Smith
Ranch Hand

Joined: Feb 25, 2009
Posts: 55
Richard Henderson wrote:
Mapping Items to Locations is more sophisticated than I need to be in this game version too. If this works I'll go more detailed in a later version which might include items by location though. That later version will also be more graphical too and might head away from text based altogether. I'm intend to work my way up through the levels of complexity with each version.



Not at all, "mapping" items to locations is just another collection:

class Room extends Location implements Foo
List<Item> items = new ArrayList<>();

...

items.add(chair);
items.add(treasure);
items.add(sword);

etc.

just be sure to remove items from the List when a player picks up the sword, etc. or, if it's a chair, maybe the player can't pick it up because chair doesn't implement Equipment? Something like that?
Richard Henderson
Ranch Hand

Joined: Feb 18, 2013
Posts: 42
Hey, Thanks again.

When I said "Mapping items to Locations", I meant body part locations. Should have been more specific.

I haven't done a lot of work with Lists of any kind yet, mainly just the stuff on the course I did.

What you've said does bring me back to the main concern I had when I posted this, which is how I will be running my Area locations and interacting them with the Player.

But before I talk more about that i'll show you what the beginning of my Player class looks like:
So you can see that Weapon and Armour are just listed as what the player is carrying. At this stage a player wont be carrying around a lot of different armour items like in WoW or other MMOs, just a Weapon with some parameters and Amour with other parameters. Ie:
So a player will just have Leather/Chainmail/Plate Armour and Rapier/Long Sword/Broad Sword for a Weapon. If I make the game long enough to warrant it, there may be magic items which will replace one of those items and they will receive their magical properties by breaking the balance between hitBonus/damBonus for Weapons (ie. + to hit = - to damage, and vice versa) and weight and armour value for Armour.

Ok, so getting back to Area locations...
It would be great to have a little list of items in each location, to go along with any monsters or traps that might already be there. But how do I record all this stuff before the Area is instantiated? I had thought I could use an Enum, like I have done with my monster types:
But instead of the creatures skill, stamina, gold/loot etc, the enum will list something like this:
Then when the player is about to enter one of these areas the game will instantiate form the enum. Each location being instantiated only once though. Other parameters included would be: direction of each exit and which location it would lead to if taken, booleans for monster, trap or special item presence etc.

A while ago I had thought that I might have to do the areas as methods in a Game class. I couldn't think how I'd get them to work as objects in their own right, but I've got my head part way around the concept now.

Sorry if this is too long. Just pick a bit and we can discus that.
Piter Smith
Ranch Hand

Joined: Feb 25, 2009
Posts: 55
Richard Henderson wrote:
Ok, so getting back to Area locations...
It would be great to have a little list of items in each location, to go along with any monsters or traps that might already be there. But how do I record all this stuff before the Area is instantiated? I had thought I could use an Enum, like I have done with my monster types:

//more creature enum types can be added here, easy like[/code]But instead of the creatures skill, stamina, gold/loot etc, the enum will list something like this:




Not too long, no worries! Too bad usenet is dead, much better for this type of discussion.

1.) why are you worried about items in an area before it's constructed?
2.) read effective Java, 2nd edition.
2b.) static factory method constructor
2c.) builder pattern

So, I happen to be using a builder for my game, here's my Player:






which is constructed as so:



so that when the object is constructed it cannot be in a indeterminate state. It's not accidentally half-built. This is an alternative to a Java Bean, which is used like so:




which can get annoying and, potentially, as you express, it might not be fully initialized.

Be aware that the player example above is immutable (or it should be, if not). String is immutable, you cannot mutate, or change, a String once it's created. (Use StringBuilder for that.)

Generally, immutable objects are preferred over mutable objects because of the concerns you raised.
Piter Smith
Ranch Hand

Joined: Feb 25, 2009
Posts: 55
Richard Henderson wrote:

So you can see that Weapon and Armour are just listed as what the player is carrying. At this stage a player wont be carrying around a lot of different armour items like in WoW or other MMOs, just a Weapon with some parameters and Amour with other parameters. Ie:




Ok, I will try to alter you code a bit, but it might not compile, it's just to give ideas:

public class Player extends Creature{
// put your fields here, exp, etc
List<Equipment> inventory = new ArrayList<>();
public Player(){}



public abstract class Weapon implements Equipment{ //etc

public abstract class Armor implements Equipment{ //etc

public class AwesomeSword extends Weapon { //it also implements Equipment, and you should say so
private int hitBonus =9;




now, back to your player. You need to, literally, map locations, or body parts, to weapons. a map is MyMap<key,value> as a scalar function. Meaning that each key is unique. You can only have one "left foot" for key, it's a set. any reference to left foot always brings up that key.
you can have a sock on each foot, that's fine. so, the values don't have to be unique.

so..., in your player

Map<BodyLocation,Equipment> wieldedAndWornEquipment = new HashMap<>();


keep in mind that Equipment is an interface, so any object which implements Equipment, like the AwesomeSword class above, is a piece of equipment and thus can be mapped to a BodyLocation.

Maybe BodyLocation could be an enum, not sure how to implement that...

Anyhow, you can add to the map:

Sword myAwesomeSword = new AwesomeSword(9); //plus 9 sword, or something
wieldedAndWornEquipment.add(Body.RIGHTHAND, myAwesomeSwordObject); //Body.RIGHTHAND is an enum

ohhh, pardon, this an EnumMap! Just thinking out loud here, so bear with me. Here's enum map example:

http://stackoverflow.com/questions/10445274/enummap-or-hashmap-if-lookup-key-is-a-string

usage as so:

Map<BodyLocation, Equipment> enumMap = new EnumMap<>(BodyLocation.class); //yes, it looks weird, but it's just a map



now, in your player class, you need to go through your equipment list find objects to map to body locations


if my code sucks, or doesn't compile, etc, blame me. do ask back about any questions, this is just to give you ideas of how to use collections.

Richard Henderson
Ranch Hand

Joined: Feb 18, 2013
Posts: 42
Sorry this took a while to reply.

I'll go back to that little ordered list you posted:
1. I'm only concerned about the items before an area is instantiated because I will have to know what item(s) is(are) in each area when it is instantiated and i'll have to tell the constructor what to put there when it is instantiated. So I need to record what is in every area, which is why I was consider making an Enum of them. If one of the items in a location was a chest or similar then it could have random contents.
2. Haven't read it I'll keep it in mind.
2a/b. I'm not familiar with either.

Had a look through your code too. It's a little confusing without comments. Looks like your player class has s few different constructors though, is that right? Is Builder and internal class?

After looking through what you wrote about my code again, i'm starting to figure out what you mean. So yeah, i'll be adding something like:
List<Equipment> inventory = new ArrayList<>();
But I wont be mapping items to body parts/locations with a two dimensional array because it's redundant. The player has one weapon and one armour (but might also end up able to get a shield, after more work by me) and everything else is in the inventory. The inventory will be an abstraction of the players backpack or something similar.

This is what I've started for the game controller:
The main method will create a player, a GUI and then a controller, feeding it the instance of player and GUI. Then i'll call the methods which set up the player and start the game. Once the game is started i'll probably do:
while(player.isAlive){
loadNewArea();
checkForMonsters();
checkForTraps();
checkForSpecials();
leaveArea();
}
loadNewArea will append a description string to the output text area.
checkForMonsters() looks at the hasMonsters boolean for the area and instantiates required monsters and starts a fight() if true.
checkForTraps() and CheckForSpecial() will do something similar.
Then leaveArea() will ask the player which exit they want to take and get input from them with a JOptionPane.

I can't think of a better way just yet.
Piter Smith
Ranch Hand

Joined: Feb 25, 2009
Posts: 55
Richard Henderson wrote:
After looking through what you wrote about my code again, i'm starting to figure out what you mean. So yeah, i'll be adding something like:
List<Equipment> inventory = new ArrayList<>();
But I wont be mapping items to body parts/locations with a two dimensional array because it's redundant. The player has one weapon and one armour (but might also end up able to get a shield, after more work by me) and everything else is in the inventory. The inventory will be an abstraction of the players backpack or something similar.



That's fine, you have the right idea. Basically, if you can, use List and Map wherever you can. The advantage to using collections is that you're not locked it.

Hypothetically, let's say, for whatever reason, a player gets a special power -- let's say an extra arm! And the arm is only good for x number of turns/hours/whatever.

It's very silly, but the point is that to be able to accommodate changes as much as possible. If your body parts are hard coded into the class, then you cannot really add an arm. If body parts are in a Collection, you can just add to that Collection. (Maybe a List or Set of body parts) Of course, you also want to get something usable, so you don't have to do that at all!

The builder pattern is here, it's just for reference, I don't think you need it:

http://en.wikipedia.org/wiki/Builder_pattern

It's not that I think it applies to what your doing, more to just get some ideas going.

anyhow, to read about EnumMap, try this example:

http://java2s.com/Tutorials/Java/Java_Collections/How_to_use_EnumMap_Class_.htm

if you're going to be using lots of enums, and it sounds like you will, just something to keep in mind.
Piter Smith
Ranch Hand

Joined: Feb 25, 2009
Posts: 55
Richard Henderson wrote:Sorry this took a while to reply.

I'll go back to that little ordered list you posted:
1. I'm only concerned about the items before an area is instantiated because I will have to know what item(s) is(are) in each area when it is instantiated and i'll have to tell the constructor what to put there when it is instantiated. So I need to record what is in every area, which is why I was consider making an Enum of them.



If you truly need to know what's in the area (room) before it's constructed, then you need to use one of:

http://en.wikipedia.org/wiki/Factory_method_pattern#Java
http://en.wikipedia.org/wiki/Builder_pattern

It's ok to just read the above and then not use it. Those are the best ways I know of to create objects where you know the state of the object at construction time.

Now, I don't think this requirement actually applies to you. In fact, while it might not make sense, you might not need to actually construct a room or location until the player actually enters it!

Explain why you require to record what is in every area. If you want to know what's in an area, just find out:

Area area = new Area();
area.addStuff(new Chair(Size.MEDIUM));
area.addStuff(new Gold(5000)); //what does the addStuff method do? it adds Stuff to the List<Stuff> which area has, of course.

List<Stuff> stuff = area.getStuffInThisArea(); //returns the List<Stuff>

for(Stuff s: stuff){ //iterate the List<Stuff>, looking at each object
System.out.println(s.toString());
}

voila, there are the rooms contents...no?


and, put your areas, of course, you get the idea, into a, wait for it.....collection!

List<Area> areas = new ArrayList<>();
Area room1 = new Area();
Area room2 = new Area();
areas.add(room1);
areas.add(room2);

etc...


I'm not sure why you're having the player(?) load a new area..?

let's say the player is in room #1

in your game controller, the player (a person?) might want to find the exits. so, the Player class would have:

public class Player{
...
MapOfDungeon mapOfDungeon = new MapOfDungeon();

public Set<Direction> getExits(){
return mapOfDirections.getExits();
}



and then your MapOfDungeon class needs to implement getExits() and return a Set<Direction>


something like that?


You'll have to show more code, I'm not sure where you're going with this.

You might want to put your code on github: http://www.github.com

but you'll have to put aside a day for just learning git basics and learning how to use github. Maybe more than one day...but then your code is available so that others can, literally, check it out. Just a thought.


Show me more of your controller class, or write out in english what it should do. Keep in mind that your game controller is independant of Swing. Anything you do in Swing is just, or should be, just interrogating your game controller for data.

Swing is not real MVC, it's modified MVC. Are you putting your controller into your Swing code where you create JFrames and so forth? If so, I suggest moving all your game controller stuff into its own class...

(Because Swing is modified MVC, it's a terrible example of MVC for this, in my opinion. A GUI controller is intertwined with the view, it's very odd. The temptation is to then add more and more logic to your GUI, which is orthogonal to the purpose behind MVC. Perhaps this point is causing confusion.)
Richard Henderson
Ranch Hand

Joined: Feb 18, 2013
Posts: 42
Haven't got time for a proper answer yet.

I'll just say that I might have the use of the MVC term incorrect.

I'm using swing and the GUI as the View.

If the Controller part of MVC is what changes and controls what you see on the view then I have a combined controller and view in the GUI class.

The class I've called GameController is the mechanics of the game and if the above is correct then it is actually my Model.

There is no mechanical code in my GUI class.
Piter Smith
Ranch Hand

Joined: Feb 25, 2009
Posts: 55
Richard Henderson wrote:Haven't got time for a proper answer yet.

I'll just say that I might have the use of the MVC term incorrect.

I'm using swing and the GUI as the View.

If the Controller part of MVC is what changes and controls what you see on the view then I have a combined controller and view in the GUI class.

The class I've called GameController is the mechanics of the game and if the above is correct then it is actually my Model.

There is no mechanical code in my GUI class.


You used the term correcty and have the right idea. Your Game controller is your game controller, that's fine. Your game itself is the *model* for the Swing GUI.

Theoretically, you're right. In practice, well..

If Swing were true MVC, then it would be as you describe. However, it's *modifed* MVC. In effect, when you make a Swing application, it's inevitable to mix controller and view because of the way it's organized.

So, in your overall app, it's a sort of recursive MVC. The outer MVC is the GUI. For the GUI, the view and control get mixed together.

The "model" of the outer MVC organization is, yes, your game.

However, your game itself can and should be real MVC. That is your game needs:

view -- what it presents to the GUI //the Swing GUI observes the view, something like that
controller -- game logic, creates objects, etc //keep your game controller as it is
model -- player model, room model, etc.

If you're just making the game itself, *without* the GUI, then the *game* will probably, and should probably, be along the lines of MVC with, as you describe, a GameController class.

yes, when you then build your swing app, the GUI sits on top of the game, and, for the GUI, the game itself is the "model" for the GUI. In the swing GUI itself, it's normal to mix control with view.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: MVC for text adventure: working out how the classes interact