Il mio primo gioco: Arkanoid
Sono nuovo di Java e ho appena finito il mio primissimo gioco: Arkanoid. Apprezzerei se qualcuno potesse dare un'occhiata a questo e dirmi alcuni consigli e suggerimenti su come posso ottimizzare il mio codice. Grazie. :)
Ho 5 classi: Breaker, BlockBreakerPanel, Ball, Paddle, Block. Aspetto:
Questa è la classe principale:
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;
}
}
Risposte
Bello, uno dei miei giochi preferiti.
Quello che hai ora sono tutte le responsabilità di un programma mescolate insieme nelle stesse classi che violano allegramente il principio di responsabilità unica . Studia il modello MVC . Quindi inizia separando la fisica del tuo gioco nel proprio insieme di classi e la rappresentazione grafica in un altro insieme. Metti gli ascoltatori di chiavi e azioni nelle loro classi e crea una classe principale che collega tutti i componenti insieme.
Sposta tutti i numeri magici (come le dimensioni dello schermo) in variabili in modo da poterli modificare facilmente. Rendi le dimensioni dell'oggetto relative alle dimensioni dello schermo in modo da poter ridimensionare il gioco per diverse risoluzioni dello schermo. Tieni presente che non tutti gli schermi hanno le stesse proporzioni tra larghezza e altezza.
Evita abbreviazioni arbitrarie come posun
. Cos'è un posun?