Использование перегрузки конструктора и уже существующих статических объектов с наследованием
Это мой второй вопрос относительно проекта, который я делаю на Space Invaders.
Я реорганизовал свой код для работы с Inheritance и ArrayLists. В моем проекте классы Ship, Weapon и Bullet расширяют класс Entity (где Entity - это любая "вещь", которая может возникнуть на экране игры, имеющая координаты, ориентацию и набор спрайтов, представленных массивом). имен файлов)
В классе, который обрабатывает игровой экран, у меня есть уже существующие наборы оружия, которые можно использовать непосредственно для их статистики для удобства. Они были созданы с использованием стандартного конструктора оружия, который содержит вызов супер-конструктора к Entity.
Моя проблема связана с перегруженным конструктором для оружия: я хочу связать этот конструктор оружия с кораблем, к которому прикреплено оружие (обратите внимание, что это два отдельных оружия, которые стреляют параллельно, на расстоянии от центра корабля), так что оружие автоматически создается со свойствами, соответствующими текущему игровому сценарию (корабль отслеживает, какое оружие загрузить, а затем рисует на экране для каждого кадра).
Вот классы:
Родительский класс (Entity)
//IMMUTABLE
public class Entity extends Object
{
//FIELDS
private final double x;
private final double y;
private final double orientation;
private final String[] sprites;
//CONSTRUCTOR
public Entity(double x, double y, double orientation, String[] sprites)
{
this.x = x;
this.y = y;
this.orientation = orientation;
this.sprites = sprites;
}
//ACCESSORS
public double getX()
{
return this.x;
}
public double getY()
{
return this.y;
}
public double getOrientation()
{
return this.orientation;
}
private String[] getSprites()
{
return this.sprites;
}
}
Подклассы, Корабль и Оружие (у меня также есть Пуля, но если я решу проблему с Оружием, то это также исправит Пуля)
КОРАБЛЬ:
//IMMUTABLE
public class Ship extends Entity
{
//GLOBAL VARIABLES
public static final double SHIP_MOVE_INT = 1;
//100 hp, weapon 0, not moving, no thrusters
public static final State defState = new State(100, 0, false, false, 0);
//FIELDS
private final State state;
//CONSTRUCTOR
public Ship(double x, double y, double orientation, String[] sprites, State state)
{
super(x, y, orientation, sprites);
this.state = state;
}
//ACCESSORS
public State getState()
{
return this.state;
}
//METHODS
public void moveLeft()
{
if (this.x > 15*SHIP_MOVE_INT)
{
this.x -= SHIP_MOVE_INT;
}
}
public void moveRight()
{
if (this.x < Graphics.X_SCALE - 15*SHIP_MOVE_INT)
{
this.x += SHIP_MOVE_INT;
}
}
//Works, but revise
public void invaderPattern(double gameClock)
{
double stage1Bound = 0.3*Graphics.X_SCALE;
double stage2Bound = stage1Bound + 0.05*Graphics.Y_SCALE;
double stage3Bound = stage2Bound + stage1Bound;
double stage4Bound = stage3Bound + 0.05*Graphics.Y_SCALE;
if (gameClock < stage1Bound)
{
//Move right
this.state.setMovingRight(true);
this.state.setMovingLeft(false);
this.x += SHIP_MOVE_INT;
}
else if (gameClock >= stage1Bound && gameClock < stage2Bound)
{
//Move down
this.state.setMovingRight(false);
this.state.setMovingLeft(false);
this.y -= SHIP_MOVE_INT;
}
else if (gameClock >= stage2Bound && gameClock < stage3Bound)
{
//Move left
this.state.setMovingLeft(true);
this.state.setMovingRight(false);
this.x -= SHIP_MOVE_INT;
}
else
{
//Move down
this.state.setMovingRight(false);
this.state.setMovingLeft(false);
this.y -= SHIP_MOVE_INT;
}
}
}
ОРУЖИЕ:
//IMMUTABLE
public class Weapon extends Entity
{
//FIELDS
private final String type;
private final int damage;
private final int rof; //Rate of fire
private final int firingStage;
//CONSTRUCTORS
public Weapon(double x, double y, double orientation, String[] sprites, String type, int damage, int rof, int firingStage)
{
super(x, y, orientation, sprites);
this.type = type;
this.damage = damage;
this.rof = rof;
this.firingStage = firingStage;
}
public Weapon(double x, Ship defender, double orientation)
{
super(x, defender.getY(), orientation, GameScreen.WEAPONS[defender.getState().getWeapon()].getSprites());
this.type = GameScreen.WEAPONS[defender.getState().getWeapon()].getType();
this.damage = GameScreen.WEAPONS[defender.getState().getWeapon()].getDamage();
this.rof = GameScreen.WEAPONS[defender.getState().getWeapon()].getRof();
this.firingStage = GameScreen.WEAPONS[defender.getState().getWeapon()].getFiringStage();
}
//END OF CONSTRUCTORS
//ACCESSORS
public String getType()
{
return this.type;
}
public int getDamage()
{
return this.damage;
}
public int getRof()
{
return this.rof;
}
public int getFiringStage()
{
return this.firingStage;
}
}
Ошибка, которая следует, происходит от вызова "super" во втором конструкторе оружия, а также от this. вызовы назначения, которые следуют за ним, то есть все это не работает, ха-ха https://drive.google.com/file/d/0B7ye7Ul2JDG2cy0yak82eUZaclE/view?usp=sharing
Ссылкой на класс GameScreen (который сам будет ссылаться на Graphics) являются следующие классы:
GameScreen (мне еще нужно добавить мутаторы)
//MUTABLE - NB
public class GameScreen
{
//GLOBAL VARIABLES
public static final String HIGH_SCORE_FILE = "highScore.txt";
//FIELDS
private Ship defender;
private Weapon[] weapons;
private ArrayList invaders;
private ArrayList bullets;
private int score;
private int lives;
private int highscore;
private double gameClock;
//AVAILABLE WEAPONS
public static final Weapon[][] WEAPONS = new Weapon[][]
{
{
new Weapon(0, 0, 0, Graphics.WEAPON_SPRITES[0], "Machinegun L", 10, 20, 0),
new Weapon(0, 0, 0, Graphics.WEAPON_SPRITES[0], "Machinegun R", 10, 20, 0)
},
{
new Weapon(0, 0, 0, Graphics.WEAPON_SPRITES[1], "Plasma MG L", 20, 20, 0),
new Weapon(0, 0, 0, Graphics.WEAPON_SPRITES[1], "Plasma MG L", 20, 20, 0)
},
{
new Weapon(0, 0, 0, Graphics.WEAPON_SPRITES[2], "Photon Cannon L", 40, 5, 0),
new Weapon(0, 0, 0, Graphics.WEAPON_SPRITES[2], "Photon Cannon R", 40, 5, 0)
},
{
new Weapon(0, 0, 0, Graphics.WEAPON_SPRITES[3], "Alien Destabilizer L", 60, 10, 0),
new Weapon(0, 0, 0, Graphics.WEAPON_SPRITES[3], "Alien Destabilizer L", 60, 10, 0)
}
};
//AVAILABLE BULLETS
public static final Bullet[] BULLETS = new Bullet[] //Correspond to WEAPONS above
{
new Bullet(0, 0, 0, Graphics.BULLET_SPRITES[0], WEAPONS[0][0].getDamage()),
new Bullet(0, 0, 0, Graphics.BULLET_SPRITES[1], WEAPONS[1][0].getDamage()),
new Bullet(0, 0, 0, Graphics.BULLET_SPRITES[2], WEAPONS[2][0].getDamage()),
new Bullet(0, 0, 0, Graphics.BULLET_SPRITES[3], WEAPONS[3][0].getDamage())
};
//CONSTRUCTOR
public GameScreen(Ship defender, Weapon[] weapons, ArrayList invaders, ArrayList bullets, int score, int lives)
{
this.defender = defender;
this.weapons = weapons;
this.invaders = invaders;
this.bullets = bullets;
this.score = score;
this.lives = lives;
this.loadHighscore();
this.gameClock = 0;
}
//METHODS
public void clk()
{
this.gameClock++;
//Should only be called when the game itself is being played, not menus
}
public void loadHighscore()
{
try
{
Scanner sc = new Scanner(new File(HIGH_SCORE_FILE));
this.highscore = Integer.parseInt(sc.next());
sc.close();
}
catch(FileNotFoundException fnf)
{
System.out.println(fnf);
this.highscore = 0;
}
}
public void saveHighScore(int highscore)
{
try
{
FileWriter write = new FileWriter(HIGH_SCORE_FILE);
PrintWriter pw = new PrintWriter(write);
pw.print(this.highscore);
pw.close();
}
catch(IOException e)
{
System.out.println(e);
}
}
//ACCESSORS
public Ship getDefender()
{
return this.defender;
}
public Weapon[] getWeapons()
{
return this.weapons;
}
public ArrayList getInvaders()
{
return this.invaders;
}
public ArrayList getBullets()
{
return this.bullets;
}
public int getScore()
{
return this.score;
}
public int getHighscore()
{
return this.highscore;
}
public int getLives()
{
return this.lives;
}
public double getGameClock()
{
return this.gameClock;
}
}
ГРАФИКА:
//LIBRARY
public class Graphics
{
//GLOBAL VARIABLES
public static final int REFRESH_RATE = 20; //delay in milliseconds
public static final double X_SCALE = 100;
public static final double Y_SCALE = 100;
public static final int X_SIZE = 512;
public static final int Y_SIZE = 624;
//Cycles of 4 stage motions
public static final double gameClockMax = X_SCALE*(0.6) + Y_SCALE*(0.1);
//SPRITES
public static final String[][] SHIP_SPRITES =
{
{"BasicShip_TRANS.png"}, //Defender [0][...]
{"BasicInvader_TRANS.png"} //Invader [1][...]
};
public static final String[][] WEAPON_SPRITES =
{
{"MG_L_TRANS.png", "MG_R_TRANS.png"}, //Machine Gun [0][...]
{"PMG_L_TRANS.png", "PMG_R_TRANS.png"}, //Plasma Machine Gun [1][...]
{"PC_L_TRANS.png", "PC_R_TRANS.png"}, //Photon Cannon [2][...]
{"AD_L_TRANS.png", "AD_R_TRANS.png"} //Alien Destabilizer [3][...]
};
public static final String[][] BULLET_SPRITES =
{
{"MG_PROJ_TRANS.png"},
{"PMG_PROJ_TRANS.png"},
{"PC_PROJ_TRANS.png"},
{"AD_PROJ.png"}
};
//END OF SPRITES
//FUNCTIONS
public static void drawMenu()
{
StdDraw.clear(StdDraw.GRAY);
StdDraw.text(50, 80, "THE SWARM");
StdDraw.text(50, 50, "P - Play");
StdDraw.text(50, 40, "Q - Quit");
}
public static void init()
{
StdDraw.setCanvasSize(X_SIZE, Y_SIZE);
StdDraw.setXscale(0.0, X_SCALE);
StdDraw.setYscale(0.0, Y_SCALE);
drawMenu();
}
public static void drawShip(int type, Ship ship) // type: 0 Defender , 1 Invader
{
if (type > 1 || type < 0)
{
System.out.println("Invalid ship type");
return;
}
int hp = ship.getState().getHealth();
if (hp > 80) StdDraw.picture(ship.getX(), ship.getY(), SHIP_SPRITES[type][0]);
//TODO
}
public static double orientation(Ship defender) //Determine weapon orientation to mouse pointer direction
{
//Clockwise rotation thus 270 + theta
if (defender.getX() < StdDraw.mouseX())
{
if (defender.getY() < StdDraw.mouseY())
{
return 270 + Math.toDegrees(Math.atan((StdDraw.mouseY() - defender.getY())/(StdDraw.mouseX() - defender.getX())));
}
else
{
return 270;
}
}
else if (defender.getX() > StdDraw.mouseX())
{
if (defender.getY() < StdDraw.mouseY())
{
return (180) + (270 + Math.toDegrees(Math.atan((StdDraw.mouseY() - defender.getY())/(StdDraw.mouseX() - defender.getX()))));
}
else
{
return 90;
}
}
else
{
return 0;
}
}
public static void drawWeapons(Weapon[] weapons)
{
//Left
StdDraw.picture
(
weapons[0].getX(),
weapons[0].getY(),
weapons[0].getSprites()[0],
weapons[0].getOrientation()
);
//Right
StdDraw.picture
(
weapons[1].getX(),
weapons[1].getY(),
weapons[1].getSprites()[1],
weapons[1].getOrientation()
);
}
public static void drawBullet(Bullet bullet)
{
StdDraw.picture
(
bullet.getX(),
bullet.getY(),
bullet.getSprites()[0],
bullet.getOrientation()
);
}
//Primary function
public void animate(GameScreen gs)
{
//TODO
//accept display of stats (hp, lives, score, etc)
/* Order of drawing:
* 1 - Background
* 2 - Borders
* 3 - Stats
* 4 - Thrusters
* 5 - Weapons
* 6 - Ships
* 7 - Bullets
* 8 - Effects
* 9 - Notifications (Combo indicators etc)
*/
//1
StdDraw.clear(StdDraw.GRAY);
//5
drawWeapons(gs.getWeapons());
//6
drawShip(gs.getDefender());
for (int i = 0; i < gs.getInvaders().size(); i++)
{
gs.getInvaders().get(i).invaderPattern(gs.getGameClock());
drawShip(gs.getInvaders().get(i));
}
//REFRESH RATE DELAY
StdDraw.show(REFRESH_RATE);
}
}
Подводя итог, я пытаюсь перегрузить конструктор оружия, чтобы он настраивался с использованием существующих конфигураций оружия (перечисленных в GameScreen, созданных с использованием первого конструктора оружия), одна из которых будет выбрана в зависимости от состояния типа корабля. Компилятор довольно жалуется на это, и я пытаюсь определить, почему>.<
2 ответа
Моя проблема была двоякой:
В GameScreen я сделал WEAPONS двумерным массивом, тогда как в перегруженном конструкторе оружия я пытался получить доступ только к одному измерению, возвращая массив вместо одного объекта оружия.
Во-вторых, по какой-то глупой причине я сделал метод getSprites в Entity закрытым, а не общедоступным, поэтому он был недоступен для перегруженного конструктора.
GameScreen.Weapons
это двумерный массив, определенный следующим образом:
public static final Weapon[][] WEAPONS
Это означает, что у вас есть двумерный массив оружия типа.
Если вы используете, например, это GameScreen.Weapons[0]
возвращает первую строку в массиве, то есть одномерный массив оружия. И массив не имеет метод, как .getDamage()
PS: я думаю, что вы неправильно поняли, что такое многомерный массив, я предлагаю поискать некоторые учебные пособия (может быть, достаточно картинок, это довольно просто, двумерный массив - это матрица)