Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (536)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  creating classes based on enum  (Read 1247 times)
0 Members and 1 Guest are viewing this topic.
Offline aufde

Senior Newbie





« Posted 2012-12-27 00:02:17 »

I want to use an enum type to determine which equipment needs to be equipped on character creation. The only way I see to do it now would be a switch statement and create the right equipment in each case:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
public AllEquips(PlayerCharacter.Classes clazz){
      switch(clazz){
      case WARRIOR:
         weapon = new WarriorWeapon1();
         head = new WarriorHead1();
         break;
      case PRIEST:
         weapon = new PriestWeapon1();
         head = new PriestHead1();
         break;
      }
   }


Would there be a way to get a class based off of the enum passed, so I would be able to make (clazz)Weapon1. That way I would only need one block of code for all of the character classes instead of one for each.
Offline actual

JGO Coder


Medals: 23



« Reply #1 - Posted 2012-12-27 01:19:39 »

I'm not sure I understand what it is you are trying to accomplish here. Do you want things in an enum because you want all of the equipment code in one place? Here is a way to do it, although it doesn't use an Enum. (It uses static methods which some people don't like).

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public class Equip {


   public static void equip(Warrior warrior) {
       warrior.setWeapon(new WarriorWeapon1());
       warrior.setHead(new WarriorHead1());
   }


   public static void equip(Priest priest) {
      priest.setWeapon(new PriestWeapon1());
      priest.setHead(new PriestHead1());
  }
}


Can you explain a bit more what you mean by "one block of code" and "(clazz)Weapon1"?  It might make it easier to help you.
Offline sproingie

JGO Kernel


Medals: 202



« Reply #2 - Posted 2012-12-27 01:29:12 »

How about:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
class Warrior {
  public void equip() {
    setWeapon(new WarriorWeapon1());
    setHead(new WarriorHead1());
  }
}

class Priest {
  public void equip() {
    setWeapon(new PriestWeapon1());
    setHead(new PriestHead1());
  }
}


Then consider better organization of weapons and heads (inner classes perhaps) and whether you even need this method at all or could make them field defaults, and so on.  But at least you'd have a start at putting it in the right place.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline aufde

Senior Newbie





« Reply #3 - Posted 2012-12-27 02:08:07 »

Wow, I just spent 10 minutes trying to explain what I wanted to do before I realized it would be waaaaay easier to put this stuff in each character class kind of like what sproingie suggested.

I still feel like I'll run into this issue at some point again (plus I'm really curious if its possible). So I'm going to try an articulate myself better this time.

So I have a class called WarriorWeapon1 and PriestWeapon1 that both extend Weapon. All level one weapons would be named in the same convention( <insert class name here>Weapon1 ). If I had a method called createWeapon(String className) how would you make it create the appropriate weapon? (I guess it doesn't have to be enum)
1  
2  
3  
4  
5  
public Weapon createWeapon(String className){
     String temp = className + "Weapon1";
     Weapon wpn = temp.createInstanceOf(); //this is obviously wrong, but can you use class loader or something?
    return wpn;
}


I've never used classLoader so I'm not even sure if that's what would be used. This is really hard to explain when I have no clue where to start coding this  Huh

Anyways, I know how to fix my original problem, but I still want to know if it's possible to do it that way because I think it would be useful. Hopefully that makes more sense because I don't know how to explain it better  Smiley
Offline sproingie

JGO Kernel


Medals: 202



« Reply #4 - Posted 2012-12-27 02:36:30 »

Inner classes are one way to do it.  Feeling a little lazy to paste any new code sections, but this thread explains the pattern quite well: http://stackoverflow.com/questions/7588091/how-to-override-extend-an-inner-class-from-a-subclass

I'm not sure about the wisdom of this pattern for specific domain classes like RPG objects, weapons and whatnot, it's really more suited for more abstract patterns.  If you need to differentiate the behaviors of a sword vs a mace vs a halberd, you should look into composition before subclassing.
Offline OttoMeier

Senior Member


Medals: 4
Projects: 1



« Reply #5 - Posted 2012-12-27 02:43:58 »

I think it would be useful.
i doubt that actually it sound like a terrible idee.

Sounds like you try to reinvent a dependency injection framework.
http://code.google.com/p/google-guice/

A warrier have a deppendency to weapon and head.
You can make that clear with using those dependeny as constuctor parameter:

1  
2  
3  
4  
5  
6  
7  
8  
9  
class Unit{
  private final Weapon weapon ;
  private final Head head

  public Unit(Weapon weapon , Head head) {
    this.weapon = weapon;
    this.head = head;
  }
}


1  
2  
3  
4  
5  
class WarriorFactory {
  public Unit createWarrior(int level) {
    return new Unit(new WarriorWeapon(level),new WarriorHead(level));
  }
}

you can google for more information ( "manuel dependency injection" )


btw.:
Dont use a namingconvention for classname (you will lose the IDE tooling, eg renaming) instead use annotations.
createInstanceOf() = class.newInstance()
http://stackoverflow.com/questions/4865153/loading-a-class-from-a-string

Offline actual

JGO Coder


Medals: 23



« Reply #6 - Posted 2012-12-27 03:02:24 »

Ok, I understand better now what you are after I think.  I have found myself in a similar situation where it felt like I was duplicating code. It was a similar case where I have a library of things and every time I add a new subtype, I also have to remember to create a new entry for the new thing.

I have issues with what you have because reflection is slow, using String keys makes things a pain, and you are relying on naming conventions. If you use an Enum, you are right back to where you started where you have to specify every item in the enum class. I also don't like reflection because it usually means more runtime errors that may have been compiler errors.

Having said all of that....one thing you could do to make it more palatable is to do all of your reflecting once up front, so you didn't need to do it every time you wanted to equip someone with something new. You could use the Reflections library to get a listing of all of the classes that subclass Weapon. You could then put a new instance of each class it into a Map where the key is the name. This would give you a library of "prototypes" that you could pull from. If you had an abstract getPrototype() method in the Weapon class each subclass could have code that would create a new "blank weapon" of that type. You could also override clone().
   
That all being said, I still don't like the approach and wouldn't use it. Another problem is what happens when you would like to pass in parameters at creation time? I knocked up in the browser window of how something like this might look....I am sure there are some mistakes. The code below could all be in a WeaponLibrary class. The only thing I really like about this is that you can create a new Weapon subclass and it will be made available here without having to also remember to add fields to enum classes or to if-then statements.

<CoverMyButt>I just did this as an exercise, I don't think I would use code like this...</CoverMyButt>


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
// A map that holds a list of weapon prototypes, that will be indexed by their name.
private Map<String,Weapon> weaponPrototypes;

public void init() {

   weaponPrototypes = new HashMap<String,Weapon>();

   // Assume I have a list of all subclasses from the Reflections library.....I have no idea how it works.
  List<ClassSpec> weaponsClasses = Reflections.getSubClassesOf(Weapon.class);

  // I am guessing that the Reflections library allows you to get an object that has information about the class.
  for (ClassSpec classSpec : weaponsClasses) {
        // Use the prefix to access the name. (7 letters in Weapon1)
       // So WarriorWeapon1 should become Warrior
       String weaponPrefix = classSpec.getName(0,classSpec.getName().length-7);
      // Add a new instance of the weapon class to the map.
     prototypes.put(weaponPrefix,classSpec.getClass().newInstance();
}


// Returns a new copy of the prototype weapon based on its name.
public Weapon getWeapon(String weapon) {
   return prototypes.get(weapon).getPrototype();
}

Offline JohnyCilohokla

Senior Newbie


Exp: 2 years



« Reply #7 - Posted 2012-12-27 03:30:20 »

Another way would be to allow the items to be copied.
And then storing items in array based on enum.

As you will probably want to save and load the equipment. You can use it to copy items.
All you will need to do is to add 1 function to the main item class that will take in item and return a copy of that item, by saving the item passed in to a buffer and then loading the new item from that buffer.

1  
2  
3  
4  
5  
6  
7  
8  
9  
public class Item{
   //make sure you have an empty constructor (without variables)
  Item (Item in){
      //check for null input here
     Item out = in.getClass().newInstance(); // you will need to catch exceptions here
     out.loadFromBuffer(in.saveToBuffer());
      return out;
   }
}
Offline HeroesGraveDev

JGO Kernel


Medals: 239
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #8 - Posted 2012-12-27 03:47:29 »

Another option is to pass the arguments to a constructor.
(And if you're feeling lazy/have too many arguments create an enum of all the different types of that class and a utitilty/factory class which automatically fills in the data that is consistent throughout that type.)

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
public enum CharacterType
{

WARRIOR1,
WARRIOR2,
PRIEST1; //etc.

}

public class Warrior extends Character
{

public Warrior(Weapon w, Head h)
{

this.weapon = w;
this.head = h;

}

}

public class CharacterCreator
{

public static Character create(CharacterType t)
{

switch(t)
{

case WARRIOR1:
      return new Warrior(Weapon1, Head1);
case WARRIOR2:
      return new Warrior(Weapon2, Head2);
case PRIEST1:
      return new Priest(Weapon3, Head3);

}

return null;

}

}


I apologise for the lack of indentation. This was typed from iOS.

Obviously you have to rename Character.class to avoid conflict with java.lang.Character

Offline marcuiulian13

Senior Member


Medals: 5
Exp: 3 years



« Reply #9 - Posted 2012-12-27 12:10:08 »

Why don't you just add a new "type" variable and check if it's suitable to the character?

Getting a project done is by far the most hard thing in game development.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CogWheelz (15 views)
2014-07-30 21:08:39

Riven (22 views)
2014-07-29 18:09:19

Riven (14 views)
2014-07-29 18:08:52

Dwinin (12 views)
2014-07-29 10:59:34

E.R. Fleming (32 views)
2014-07-29 03:07:13

E.R. Fleming (12 views)
2014-07-29 03:06:25

pw (42 views)
2014-07-24 01:59:36

Riven (42 views)
2014-07-23 21:16:32

Riven (30 views)
2014-07-23 21:07:15

Riven (31 views)
2014-07-23 20:56:16
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!