Moja pierwsza gra - Arkanoid
Jestem nowy w Javie i właśnie skończyłem swoją pierwszą grę - Arkanoid. Byłbym wdzięczny, gdyby ktoś mógł na to spojrzeć i przekazać mi kilka rad i wskazówek, jak zoptymalizować mój kod. Dziękuję Ci. :)
Mam 5 klas - Breaker, BlockBreakerPanel, Ball, Paddle, Block. Popatrz:
Oto główne klasy:
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;
}
}
Odpowiedzi
Fajnie, jedna z moich ulubionych gier.
To, co teraz masz, to wszystkie obowiązki programu zmieszane razem w tych samych klasach, wesoło naruszając zasadę pojedynczej odpowiedzialności . Przestudiuj model MVC . Następnie zacznij od rozdzielenia fizyki gry na własny zestaw klas i graficznej reprezentacji na inny zestaw. Umieść detektory klucza i akcji w osobnych klasach i utwórz klasę główną, która łączy wszystkie komponenty razem.
Przenieś wszystkie magiczne liczby (takie jak rozmiar ekranu) do zmiennych, aby można je było łatwo zmienić. Dopasuj rozmiary obiektów do rozmiaru ekranu, abyś mógł skalować grę do różnych rozdzielczości ekranu. Weź pod uwagę, że nie wszystkie ekrany mają ten sam współczynnik szerokości do wysokości.
Unikaj dowolnych skrótów, takich jak posun. Co to jest posun?