Моя первая игра - Арканоид
Я новичок в java и только что закончил свою самую первую игру - Arkanoid. Я был бы признателен, если бы кто-нибудь мог взглянуть на это и дать мне несколько советов и подсказок, как я могу оптимизировать свой код. Спасибо. :)
У меня 5 классов - Breaker, BlockBreakerPanel, Ball, Paddle, Block. Смотреть:
Это основной класс:
public class Breaker {
private BlockBreakerPanel panel;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Breaker b = new Breaker();
b.show();
}
private void show() {
JFrame frame = new JFrame("Block Breaker");
frame.setSize(490, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.panel = new BlockBreakerPanel(this);
frame.add(this.panel);
frame.setVisible(true);
}
public BlockBreakerPanel getPanel() {
return this.panel;
}
}
class BlockBreakerPanel extends JPanel implements KeyListener, ActionListener
{
private ArrayList<Blocks> blocks = new ArrayList<>();
private final Paddle player;
private final Ball ball;
private final Breaker game;
private boolean gameOver;
private int score;
private boolean start;
public BlockBreakerPanel(Breaker game) {
setBackground(Color.BLACK);
for (int j = 0; j < 3; j++) {
for (int i = 0; i < 8; i++) {
this.blocks.add(new Blocks(i * 60 + 2, j * 40 + 5, 50, 30));
}
}
this.player = new Paddle(game);
this.ball = new Ball(game);
this.gameOver = false;
this.score = 0;
this.start = false;
Timer t = new Timer(5, this);
t.start();
addKeyListener(this);
setFocusable(true);
this.game = game;
}
public void addPoint() {
this.score++;
}
public void isGameOver() {
this.gameOver = true;
}
public ArrayList<Blocks> getBlocks() {
return this.blocks;
}
public Paddle getPlayer() {
return this.player;
}
public void paint(Graphics g) {
super.paintComponent(g);
this.blocks.forEach((block) -> {
block.paint(g);
});
this.player.paint(g);
this.ball.paint(g);
if (!this.start) {
g.setFont(new Font("Calibri", Font.BOLD, 35));
g.setColor(Color.WHITE);
g.drawString("Pressed enter to start a game", 20, 300);
}
g.setFont(new Font("Calibri", Font.BOLD, 20));
g.setColor(Color.WHITE);
g.drawString(String.valueOf(this.score), 450, 540);
if (this.gameOver) {
g.setFont(new Font("Calibri", Font.BOLD, 80));
g.setColor(Color.WHITE);
g.drawString("Game Over", 60, 300);
} else if (this.blocks.isEmpty()) {
this.gameOver = true;
g.setFont(new Font("Calibri", Font.BOLD, 80));
g.setColor(Color.WHITE);
g.drawString("You won", 80, 300);
}
}
private void update() {
this.ball.move();
repaint();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
this.start = true;
}
this.player.pressed(e.getKeyCode());
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
if (!this.gameOver && this.start) {
this.update();
}
}
}
class Blocks {
private final int x;
private final int y;
private final int width;
private final int height;
public Blocks(int a, int b, int w, int h) {
this.x = a;
this.y = b;
this.width = w;
this.height = h;
}
public void paint(Graphics g) {
g.setColor(Color.pink);
g.drawRect(this.x, this.y, this.width, this.height);
g.fillRect(this.x, this.y, this.width, this.height);
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
}
public class Paddle {
private int x;
private final int y;
private final int width;
private final int height;
private final int posun;
private final Breaker game;
/**
*
* @param game
*/
public Paddle(Breaker game) {
this.x = 245 - (60/2);
this.y = 540;
this.width = 100;
this.height = 15;
this.posun = 10;
this.game = game;
}
public int getWidth() {
return this.width;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public void paint(Graphics g) {
g.setColor(Color.CYAN);
g.drawRect(this.x, this.y, this.width, this.height);
g.fillRect(this.x, this.y, this.width, this.height);
}
void pressed(int keyCode) {
this.collision();
if (keyCode == KeyEvent.VK_RIGHT) {
this.x += this.posun;
} else if (keyCode == KeyEvent.VK_LEFT) {
this.x -= this.posun;
}
}
private void collision() {
if ((this.x + this.width) >= 490) {
this.x = 490 - this.width;
} else if (this.x <= 0) {
this.x = 0;
}
}
}
public class Ball {
private final int DIAMETER = 20;
private int x;
private int y;
private int dx;
private int dy;
private final Breaker game;
/**
*
* @param game
*/
public Ball(Breaker game) {
this.x = 245 - (DIAMETER / 2);
this.y = 500;
this.dx = 2;
this.dy = 2;
this.game = game;
}
void paint(Graphics g) {
g.setColor(Color.PINK);
g.drawOval(this.x, this.y, DIAMETER, DIAMETER);
g.fillOval(this.x, this.y, DIAMETER, DIAMETER);
}
private void checkCollision() {
boolean collision = false;
if (((this.y+DIAMETER) >= this.game.getPanel().getPlayer().getY()) && ((this.x) >= this.game.getPanel().getPlayer().getX()-2) && ((this.x+DIAMETER) <= (this.game.getPanel().getPlayer().getX()+this.game.getPanel().getPlayer().getWidth()+2))) {
collision = true;
} else if ((this.y + DIAMETER) >= 560) {
this.game.getPanel().isGameOver();
return;
}
for (Blocks block : this.game.getPanel().getBlocks()) {
if ((this.y+5 <= (block.getY() + block.getHeight())) && (this.x+5 >= block.getX()) && ((this.x+DIAMETER-5) <= block.getX()+block.getWidth())) {
this.game.getPanel().getBlocks().remove(block);
collision = true;
this.game.getPanel().addPoint();
break;
}
}
if (collision) {
this.dy = - this.dy;
}
}
public void move() {
if (this.x <= 0 || this.x >= (460 + DIAMETER)) {
this.dx = -this.dx;
} else if (this.y <= 0 || this.y >= (540 + DIAMETER)) {
this.dy = -this.dy;
}
this.checkCollision();
this.x += this.dx;
this.y += this.dy;
}
}
Ответы
Хорошая, одна из моих любимых игр.
Теперь у вас есть все обязанности программы, смешанные вместе в одни и те же классы, весело нарушающие принцип единой ответственности . Изучите модель MVC . Затем начните с разделения вашей игровой физики на их собственный набор классов и графического представления на другой набор. Поместите прослушиватели ключей и действий в их собственные классы и создайте основной класс, который соединяет все компоненты вместе.
Переместите все магические числа (например, размер экрана) в переменные, чтобы их можно было легко изменить. Установите размеры объектов относительно размера экрана, чтобы вы могли масштабировать игру для разных разрешений экрана. Учтите, что не все экраны имеют одинаковое соотношение сторон ширины к высоте.
Избегайте произвольных сокращений вроде posun. Что такое посун?