I'm writing a text based rpg in java. The problem is that I have a class which manipulates the map (2d character array) for in multiple classes. Since I want to have multiple maps (2d character arrays) and different methods to handle each character array, I've used inheritance to support different maps.
Early on I realized that the object I used to call the methods needed to be reinitialized to a different class every time a character entered that world. So I've had to change the fields in my main game loop as well as in my class files. How can I simply this.
Main Game Loop
public class GameLoop {
public static void print(char[][] array) {
for(int i = 0; i < array.length; i++) {
for(int j = 0; j < array[0].length; j++) {
System.out.print(array[i][j]);
}
System.out.println();
}
}
public GameLoop() {
Menu menu = new Menu();
Player player = new Player("John", 1, 200, 200, 50, 4, .6, .1, 0, new HashMap<>());
World w = new Town();
// World w = new Forest(2,1);
String location = "";
w.setLocation("Town");
w.setPos(1, 1);
char[][] array = w.getMap();
int[] pos = new int[2];
Scanner sc = new Scanner(System.in);
System.out.println("please input n (north), s (south), w (west) or e (east)\n" +
"c (character stats), i (inventory)");
print(array);
char dir = ' ';
while(true) {
pos = w.getPos();
location = w.getLocation();
if(!location.equals(w.getClass().getName().substring(16))) {
switch(location) {
case "Town":
w = new Town();
w.setLocation("Town");
w.setPos(7, 8);
char[][] map2 = w.getMap2();
w.setMap(map2);
array = w.getMap();
break;
case "Forest":
w = new Forest();
w.setPos(2, 1);
w.setLocation("Forest");
array = w.getMap();
break;
case "Cave":
break;
}
}
System.out.println(pos[0] + " " + pos[1] + " Location: " +
location);
System.out.println(w.getClass().getName());
dir = menu.runMenu(sc, "nNsSeEwWiIcCqQ");
switch(dir) {
case 'w':
case 'W':
w.west(player);
array = w.getMap();
print(array);
break;
case 's':
case 'S':
w.south(player);
array = w.getMap();
print(array);
break;
case 'e':
case 'E':
w.east(player);
array = w.getMap();
print(array);
break;
case 'n':
case 'N':
w.north(player);
array = w.getMap();
print(array);
break;
case 'c':
case 'C':
player.getStats();
print(array);
break;
case 'i':
case 'I':
player.getInv();
print(array);
break;
case 'q':
case 'Q':
System.out.println("You have quit the game");
System.exit(0);
break;
case 'z':
case 'Z':
System.out.println("Must input a character n, e, s, w");
print(array);
break;
default:
System.out.println("invalid key");
print(array);
break;
}// end switch
}// end while
Town map
public class Town extends World {
public Town() {
map = new char[][]{ {'*','-','-','-','-','-','-','-','-','*'},
{'|','p',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ','s',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ','h',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ',' ','>','|'},
{'*','-','-','-','-','-','-','-','-','*'} };
map2 = new char[][]{ {'*','-','-','-','-','-','-','-','-','*'},
{'|',' ',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ','s',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ','h',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ',' ',' ','|'},
{'|',' ',' ',' ',' ',' ',' ','p','>','|'},
{'*','-','-','-','-','-','-','-','-','*'} };
}
public void west(Player p) {
if(map[y][x] == 'p' && map[y][x-1] == ' ') {
map[y][x] = ' ';
map[y][--x] = 'p';
} else if(map[y][x] == 'p' && map[y][x-1] == 's') {
//Shop shop = new Shop();
} else if(map[y][x] == 'p' && map[y][x-1] == 'h') {
p.setHp(p.getMaxHp());
System.out.println("At your house you rest. Your health is refilled");
}
}
public void south(Player p) {
if(map[y][x] == 'p' && map[y+1][x] == ' ') {
map[y][x] = ' ';
map[++y][x] = 'p';
} else if(map[y][x] == 'p' && map[y+1][x] == 's') {
// Shop shop = new Shop();
} else if(map[y][x] == 'p' && map[y+1][x] == 'h') {
p.setHp(p.getMaxHp());
System.out.println("Your health is refilled");
} else if(map[y][x] == 'p' && map[y+1][x] == '>') {
System.out.println("You've entered the forest");
World world = new Forest();
setLocation("Forest");
setPos(2, 1);
map = world.getMap();
}
}
public void east(Player p) {
if(map[y][x] == 'p' && map[y][x+1] == ' ') {
map[y][x] = ' ';
map[y][++x] = 'p';
} else if(map[y][x] == 'p' && map[y][x+1] == 's') {
//Shop shop = new Shop();
} else if(map[y][x] == 'p' && map[y][x+1] == 'h') {
p.setHp(p.getMaxHp());
System.out.println("Your health is refilled");
} else if(map[y][x] == 'p' && map[y][x+1] == '>') {
System.out.println("You've entered the forest");
World world = new Forest();
setLocation("Forest");
setPos(2, 1);
map = world.getMap();
}
}
public void north(Player p) {
if(map[y][x] == 'p' && map[y-1][x] == ' ') {
map[y][x] = ' ';
map[--y][x] = 'p';
} else if(map[y][x] == 'p' && map[y][x+1] == 's') {
//Shop shop = new Shop();
} else if(map[y][x] == 'p' && map[y][x+1] == 'h') {
p.setHp(p.getMaxHp());
System.out.println("Your health is refilled");
}
}
SuperClass
public abstract class World {
protected int x;
protected int y;
protected char[][] map;
protected char[][] map2;
protected String location;
public char[][] getMap() {
return map;
}
public char[][] getMap2() {
return map2;
}
public void setMap(char[][] map) {
this.map = map;
}
public void setLocation(String location) {
this.location = location;
}
public String getLocation() {
return location;
}
public int[] getPos() {
int[] position = new int[2];
position[0] = x;
position[1] = y;
return position;
}
public void setPos(int x, int y) {
this.x = x;
this.y = y;
}
public abstract void west(Player p);
public abstract void north(Player p);
public abstract void east(Player p);
public abstract void south(Player p);
}
I was thinking, should I use a singleton pattern? I'm new to OOP so I'm kind of just trying to figure this all out.
Update: I've added the full code for the game loop so you can see that it does in fact know about the player and the map (or the world as I call it). I will look into this enum, thanks about that.
The reason I have seperated the logic for the game knowing about each map is because then the main switch statement for the game would eventually get to be hundreds of lines long. I've planned to add different collision detections for npcs, shops, monsters and events based on the map.
By creating seperating the logic I can use polymorphism to keep calling the north, west, east, south methods and keeping the logic different for each subclass of the map. Now that I am thinking more maybe some of the fields can be static for the x and y axis, and the 2d char array.