From 7e839c8069d06fbba82b2b2a2902f80025ffe2db Mon Sep 17 00:00:00 2001 From: Vichingo455 Date: Mon, 27 Oct 2025 10:50:33 +0100 Subject: [PATCH] Dino Game --- DinoGame/src/DinoGame.java | 590 +++++++++++++++++++++---------------- 1 file changed, 337 insertions(+), 253 deletions(-) diff --git a/DinoGame/src/DinoGame.java b/DinoGame/src/DinoGame.java index 3a9a912..5c122ea 100644 --- a/DinoGame/src/DinoGame.java +++ b/DinoGame/src/DinoGame.java @@ -7,6 +7,9 @@ import java.io.*; import java.util.ArrayList; import java.util.Random; import javax.sound.sampled.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; public class DinoGame extends JPanel implements ActionListener, KeyListener { // Game constants @@ -14,151 +17,178 @@ public class DinoGame extends JPanel implements ActionListener, KeyListener { private static final int HEIGHT = 400; private static final int GROUND_Y = 320; private static final int FPS = 60; - private static final int GRAVITY = 2; - private static final int JUMP_STRENGTH = -22; - - // Game state - private Timer timer; + private static final int GRAVITY = 1; + private static final int JUMP_STRENGTH = -18; + private static final int INITIAL_SPEED = 10; + private static final int MAX_SPEED = 20; + private static final int SPEED_INCREMENT = 1; + private static final int HITBOX_INSET = 8; private boolean gameStarted = false; private boolean gameOver = false; private boolean paused = false; private int score = 0; private int highScore = 0; - private double gameSpeed = 12.0; + private int gameSpeed = INITIAL_SPEED; private int frameCount = 0; - - // Player - private int dinoX = 50; - private int dinoY = GROUND_Y - 90; - private int dinoWidth = 44; - private int dinoHeight = 47; + private final int dinoX = 50; + private int dinoY; + private int dinoWidth; + private int dinoHeight; + private int dinoDuckWidth; + private int dinoDuckHeight; private int velocityY = 0; private boolean isJumping = false; private boolean isDucking = false; private int animFrame = 0; - - // Images + private int groundY; private BufferedImage dinoRun1, dinoRun2, dinoJump, dinoDead; private BufferedImage dinoDownRun1, dinoDownRun2; private BufferedImage cactus1, cactus2, cactus3, cactus4, cactus5, cactus6; private BufferedImage birdFly1, birdFly2; private BufferedImage cloud, land, gameOverImg, replayImg, hiImg; - - // Game objects - private ArrayList obstacles = new ArrayList<>(); - private ArrayList clouds = new ArrayList<>(); + private final ArrayList obstacles = new ArrayList<>(); + private final ArrayList clouds = new ArrayList<>(); private int landX = 0; - private Random rand = new Random(); + private final Random rand = new Random(); private int obstacleTimer = 0; - - // Audio + private int minObstacleDistance = 60; + private int maxObstacleDistance = 120; private Clip jumpSound, deadSound, scoreSound; + private long lastScoreTime = 0; public DinoGame() { setPreferredSize(new Dimension(WIDTH, HEIGHT)); setBackground(Color.WHITE); setFocusable(true); addKeyListener(this); - - loadImages(); - loadSounds(); - loadHighScore(); - - // Initialize clouds - for (int i = 0; i < 3; i++) { - clouds.add(new Cloud(rand.nextInt(WIDTH), 50 + rand.nextInt(100))); + setDoubleBuffered(true); + loadAssets(); + for (int i = 0; i < 5; i++) { + clouds.add(new Cloud(i * 250 + rand.nextInt(100), 50 + rand.nextInt(100))); } - - timer = new Timer(1000 / FPS, this); + resetGameData(); + Timer timer = new Timer(1000 / FPS, this); timer.start(); } - private void loadImages() { + private void loadAssets() { try { - dinoRun1 = ImageIO.read(getClass().getResourceAsStream("/dino-run-1.png")); - dinoRun2 = ImageIO.read(getClass().getResourceAsStream("/dino-run-2.png")); - dinoJump = ImageIO.read(getClass().getResourceAsStream("/dino-jump.png")); - dinoDead = ImageIO.read(getClass().getResourceAsStream("/dino-dead.png")); - dinoDownRun1 = ImageIO.read(getClass().getResourceAsStream("/dino-down-run-1.png")); - dinoDownRun2 = ImageIO.read(getClass().getResourceAsStream("/dino-down-run-2.png")); + loadImages(); + } catch (IOException e) { + String errorMsg = "Error: cannot load image resources.\n" + e.getMessage(); + System.err.println(errorMsg); + JOptionPane.showMessageDialog(this, errorMsg, "Error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + } + dinoWidth = dinoRun1.getWidth(); + dinoHeight = dinoRun1.getHeight(); + dinoDuckWidth = dinoDownRun1.getWidth(); + dinoDuckHeight = dinoDownRun1.getHeight(); + groundY = GROUND_Y - dinoHeight; + dinoY = groundY; + loadSoundsAndHighScore(); + } - cactus1 = ImageIO.read(getClass().getResourceAsStream("/cactus-1.png")); - cactus2 = ImageIO.read(getClass().getResourceAsStream("/cactus-2.png")); - cactus3 = ImageIO.read(getClass().getResourceAsStream("/cactus-3.png")); - cactus4 = ImageIO.read(getClass().getResourceAsStream("/cactus-4.png")); - cactus5 = ImageIO.read(getClass().getResourceAsStream("/cactus-5.png")); - cactus6 = ImageIO.read(getClass().getResourceAsStream("/cactus-6.png")); + private void loadImages() throws IOException { + dinoRun1 = loadImage("/dino-run-1.png"); + dinoRun2 = loadImage("/dino-run-2.png"); + dinoJump = loadImage("/dino-jump.png"); + dinoDead = loadImage("/dino-dead.png"); + dinoDownRun1 = loadImage("/dino-down-run-1.png"); + dinoDownRun2 = loadImage("/dino-down-run-2.png"); + cactus1 = loadImage("/cactus-1.png"); + cactus2 = loadImage("/cactus-2.png"); + cactus3 = loadImage("/cactus-3.png"); + cactus4 = loadImage("/cactus-4.png"); + cactus5 = loadImage("/cactus-5.png"); + cactus6 = loadImage("/cactus-6.png"); + birdFly1 = loadImage("/bird-fly-1.png"); + birdFly2 = loadImage("/bird-fly-2.png"); + cloud = loadImage("/cloud.png"); + land = loadImage("/land.png"); + gameOverImg = loadImage("/game-over.png"); + replayImg = loadImage("/replay.png"); + hiImg = loadImage("/hi.png"); + } - birdFly1 = ImageIO.read(getClass().getResourceAsStream("/bird-fly-1.png")); - birdFly2 = ImageIO.read(getClass().getResourceAsStream("/bird-fly-2.png")); - - cloud = ImageIO.read(getClass().getResourceAsStream("/cloud.png")); - land = ImageIO.read(getClass().getResourceAsStream("/land.png")); - gameOverImg = ImageIO.read(getClass().getResourceAsStream("/game-over.png")); - replayImg = ImageIO.read(getClass().getResourceAsStream("/replay.png")); - hiImg = ImageIO.read(getClass().getResourceAsStream("/hi.png")); - } catch (Exception e) { - System.err.println("Error loading images: " + e.getMessage()); - e.printStackTrace(); + private BufferedImage loadImage(String path) throws IOException { + InputStream is = getClass().getResourceAsStream(path); + if (is == null) { + throw new IOException("Resource not found: " + path); + } + try { + return ImageIO.read(is); + } catch (IOException e) { + throw new IOException("Cannot read image: " + path, e); } } - private void loadSounds() { + private void loadSoundsAndHighScore() { + new Thread(() -> { + try { + jumpSound = loadSound("/jump.wav"); + deadSound = loadSound("/dead.wav"); + scoreSound = loadSound("/score.wav"); + loadHighScore(); + } catch (Exception e) { + System.err.println("Error loading sounds and high score: " + e.getMessage()); + } + }).start(); + } + + private Clip loadSound(String path) { try { - jumpSound = AudioSystem.getClip(); - jumpSound.open(AudioSystem.getAudioInputStream(getClass().getResourceAsStream("/jump.wav"))); - - deadSound = AudioSystem.getClip(); - deadSound.open(AudioSystem.getAudioInputStream(getClass().getResourceAsStream("/dead.wav"))); - - scoreSound = AudioSystem.getClip(); - scoreSound.open(AudioSystem.getAudioInputStream(getClass().getResourceAsStream("/scoreup.wav"))); + InputStream is = getClass().getResourceAsStream(path); + if (is != null) { + InputStream bufferedIs = new BufferedInputStream(is); + AudioInputStream ais = AudioSystem.getAudioInputStream(bufferedIs); + Clip clip = AudioSystem.getClip(); + clip.open(ais); + return clip; + } } catch (Exception e) { - System.err.println("Error loading sounds: " + e.getMessage()); - e.printStackTrace(); + System.err.println("Cannot load sound: " + path + " - " + e.getMessage()); } + return null; } private void loadHighScore() { try { - InputStream is = getClass().getResourceAsStream("/best-scores.txt"); - if (is != null) { - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - String line = reader.readLine(); - if (line != null) { - highScore = Integer.parseInt(line.trim()); - } - reader.close(); + Path scoreFile = Paths.get(System.getProperty("user.home"), "dino-best-scores.txt"); + if (Files.exists(scoreFile)) { + String content = new String(Files.readAllBytes(scoreFile)); + highScore = Integer.parseInt(content.trim()); } } catch (Exception e) { highScore = 0; + System.err.println("Cannot load high score: " + e.getMessage()); } } private void saveHighScore() { - try { - // Save to user's home directory since resources folder is read-only - String userHome = System.getProperty("user.home"); - File scoresFile = new File(userHome, "dino-best-scores.txt"); - PrintWriter writer = new PrintWriter(new FileWriter(scoresFile)); - writer.println(highScore); - writer.close(); - } catch (IOException e) { - System.err.println("Error saving high score: " + e.getMessage()); - } + new Thread(() -> { + try { + Path scoreFile = Paths.get(System.getProperty("user.home"), "dino-best-scores.txt"); + Files.write(scoreFile, String.valueOf(highScore).getBytes()); + } catch (IOException e) { + System.err.println("Error saving high score: " + e.getMessage()); + } + }).start(); } private void playSound(Clip clip) { if (clip != null) { - try { - if (clip.isRunning()) { - clip.stop(); + new Thread(() -> { + try { + if (clip.isRunning()) { + clip.stop(); + } + clip.setFramePosition(0); + clip.start(); + } catch (Exception e) { + // Silently fail } - clip.setFramePosition(0); - clip.start(); - } catch (Exception e) { - System.err.println("Error playing audio: " + e.getMessage()); - } + }).start(); } } @@ -170,85 +200,99 @@ public class DinoGame extends JPanel implements ActionListener, KeyListener { } if (!gameOver) { - frameCount++; - - // Update score - if (frameCount % 6 == 0) { - score++; - if (score % 100 == 0) { - playSound(scoreSound); - } - } - - // Increase speed - if (frameCount % 600 == 0) { - gameSpeed += 0.5; - } - - // Update dino - if (isJumping) { - velocityY += GRAVITY; - dinoY += velocityY; - - if (dinoY >= GROUND_Y - 90) { - dinoY = GROUND_Y - 90; - isJumping = false; - velocityY = 0; - } - } - - // Animation - if (frameCount % 5 == 0) { - animFrame = (animFrame + 1) % 2; - } - - // Update ground - landX -= (int)gameSpeed; - if (land != null && landX <= -land.getWidth()) { - landX = 0; - } - - // Update clouds - for (Cloud c : clouds) { - c.x -= 2; - if (cloud != null && c.x < -cloud.getWidth()) { - c.x = WIDTH + rand.nextInt(200); - c.y = 50 + rand.nextInt(100); - } - } - - // Spawn obstacles - obstacleTimer++; - if (obstacleTimer > 60 + rand.nextInt(60)) { - spawnObstacle(); - obstacleTimer = 0; - } - - // Update obstacles - for (int i = obstacles.size() - 1; i >= 0; i--) { - Obstacle obs = obstacles.get(i); - obs.x -= (int)gameSpeed; - - if (obs.x < -obs.width) { - obstacles.remove(i); - } else if (checkCollision(obs)) { - gameOver = true; - playSound(deadSound); - if (score > highScore) { - highScore = score; - saveHighScore(); - } - } - } + updateGameLogic(); } repaint(); } + private void updateGameLogic() { + frameCount++; + updateScoreAndSpeed(); + updatePlayer(); + updateEnvironment(); + spawnAndMoveObstacles(); + } + private void updateScoreAndSpeed() { + if (frameCount % 6 == 0) { + score++; + if (score % 100 == 0) { + long currentTime = System.currentTimeMillis(); + if (currentTime - lastScoreTime > 100) { + playSound(scoreSound); + lastScoreTime = currentTime; + } + } + } + if (frameCount % 900 == 0 && gameSpeed < MAX_SPEED) { + gameSpeed += SPEED_INCREMENT; + minObstacleDistance = Math.max(40, 60 - ((gameSpeed - INITIAL_SPEED) * 2)); + maxObstacleDistance = Math.max(80, 120 - ((gameSpeed - INITIAL_SPEED) * 3)); + } + } + private void updatePlayer() { + if (isJumping) { + velocityY += GRAVITY; + dinoY += velocityY; + + if (dinoY >= groundY) { + dinoY = groundY; + isJumping = false; + velocityY = 0; + } + } + int animSpeed = Math.max(3, 6 - ((gameSpeed - INITIAL_SPEED) / 2)); + if (frameCount % animSpeed == 0) { + animFrame = (animFrame + 1) % 2; + } + } + private void updateEnvironment() { + landX -= gameSpeed; + if (land != null && landX <= -land.getWidth()) { + landX = 0; + } + for (Cloud c : clouds) { + c.x -= 1; + if (cloud != null && c.x < -cloud.getWidth()) { + c.x = WIDTH + rand.nextInt(200); + c.y = 50 + rand.nextInt(100); + } + } + } + private void spawnAndMoveObstacles() { + obstacleTimer++; + int spawnDelay = minObstacleDistance + rand.nextInt(maxObstacleDistance - minObstacleDistance); + if (obstacleTimer > spawnDelay) { + spawnObstacle(); + obstacleTimer = 0; + } + for (int i = obstacles.size() - 1; i >= 0; i--) { + Obstacle obs = obstacles.get(i); + obs.x -= gameSpeed; + + if (obs.x < -obs.width) { + obstacles.remove(i); + } else if (checkCollision(obs)) { + gameOver = true; + playSound(deadSound); + if (score > highScore) { + highScore = score; + saveHighScore(); + } + } + } + } + private void spawnObstacle() { + if (!obstacles.isEmpty()) { + Obstacle last = obstacles.get(obstacles.size() - 1); + if (last.x > WIDTH - 200) { + return; + } + } + int birdChance = Math.min(4, ((gameSpeed - INITIAL_SPEED) / 2) + 2); int type = rand.nextInt(10); - if (type < 7) { - // Cactus + if (type < (10 - birdChance)) { BufferedImage[] cacti = {cactus1, cactus2, cactus3, cactus4, cactus5, cactus6}; BufferedImage cactusImg = cacti[rand.nextInt(cacti.length)]; if (cactusImg != null) { @@ -257,38 +301,66 @@ public class DinoGame extends JPanel implements ActionListener, KeyListener { cactusImg, false)); } } else { - // Bird if (birdFly1 != null) { - int birdY = GROUND_Y - 44 - rand.nextInt(2) * 80; - obstacles.add(new Obstacle(WIDTH, birdY, 46, 40, birdFly1, true)); + int birdHeight = birdFly1.getHeight(); + int[] heights = { + GROUND_Y - birdHeight, // Basso + GROUND_Y - birdHeight - 100, // Alto + GROUND_Y - birdHeight - 60 // Medio + }; + int birdY = heights[rand.nextInt(heights.length)]; + obstacles.add(new Obstacle(WIDTH, birdY, + birdFly1.getWidth(), birdFly1.getHeight(), + birdFly1, true)); } } } + private Rectangle getDinoHitbox() { + if (isDucking) { + return new Rectangle( + dinoX + HITBOX_INSET, + GROUND_Y - dinoDuckHeight + HITBOX_INSET, + dinoDuckWidth - 2 * HITBOX_INSET, + dinoDuckHeight - 2 * HITBOX_INSET + ); + } else { + return new Rectangle( + dinoX + HITBOX_INSET, + dinoY + HITBOX_INSET, + dinoWidth - 2 * HITBOX_INSET, + dinoHeight - 2 * HITBOX_INSET + ); + } + } private boolean checkCollision(Obstacle obs) { - int dinoActualHeight = isDucking ? 26 : dinoHeight; - int dinoActualY = isDucking ? GROUND_Y - 90 : dinoY; - - Rectangle dinoRect = new Rectangle(dinoX + 5, dinoActualY + 5, - dinoWidth - 10, dinoActualHeight - 10); - Rectangle obsRect = new Rectangle(obs.x + 5, obs.y + 5, - obs.width - 10, obs.height - 10); + Rectangle dinoRect = getDinoHitbox(); + Rectangle obsRect = new Rectangle( + obs.x + HITBOX_INSET, + obs.y + HITBOX_INSET, + obs.width - 2 * HITBOX_INSET, + obs.height - 2 * HITBOX_INSET + ); return dinoRect.intersects(obsRect); } - - private void reset() { - gameOver = false; - gameStarted = true; + private void resetGameData() { score = 0; - gameSpeed = 12.0; + gameSpeed = INITIAL_SPEED; frameCount = 0; - dinoY = GROUND_Y - 90; + dinoY = groundY; velocityY = 0; isJumping = false; isDucking = false; obstacles.clear(); obstacleTimer = 0; + minObstacleDistance = 60; + maxObstacleDistance = 120; + } + private void reset() { + gameOver = false; + gameStarted = true; + resetGameData(); } @Override @@ -296,45 +368,40 @@ public class DinoGame extends JPanel implements ActionListener, KeyListener { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - // Draw clouds + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); + drawClouds(g2d); + drawGround(g2d); + drawDino(g2d); + drawObstacles(g2d); + drawUI(g2d); + drawOverlays(g2d); + } + private void drawClouds(Graphics2D g2d) { for (Cloud c : clouds) { if (cloud != null) { g2d.drawImage(cloud, c.x, c.y, null); } } - - // Draw ground + } + private void drawGround(Graphics2D g2d) { if (land != null) { g2d.drawImage(land, landX, GROUND_Y, null); g2d.drawImage(land, landX + land.getWidth(), GROUND_Y, null); } - - // Draw ground line - g2d.setColor(Color.BLACK); + g2d.setColor(new Color(83, 83, 83)); g2d.fillRect(0, GROUND_Y - 2, WIDTH, 2); - - // Draw dino - BufferedImage dinoImg; - if (gameOver) { - dinoImg = dinoDead; - } else if (isJumping) { - dinoImg = dinoJump; - } else if (isDucking) { - dinoImg = (animFrame == 0) ? dinoDownRun1 : dinoDownRun2; - } else { - dinoImg = (animFrame == 0) ? dinoRun1 : dinoRun2; - } - + } + private void drawDino(Graphics2D g2d) { + BufferedImage dinoImg = getDinoImage(); if (dinoImg != null) { if (isDucking) { - g2d.drawImage(dinoImg, dinoX, GROUND_Y - 26, 59, 26, null); + g2d.drawImage(dinoImg, dinoX, GROUND_Y - dinoDuckHeight, null); } else { g2d.drawImage(dinoImg, dinoX, dinoY, null); } } - - // Draw obstacles + } + private void drawObstacles(Graphics2D g2d) { for (Obstacle obs : obstacles) { if (obs.isBird) { BufferedImage birdImg = (frameCount % 10 < 5) ? birdFly1 : birdFly2; @@ -347,17 +414,17 @@ public class DinoGame extends JPanel implements ActionListener, KeyListener { } } } - - // Draw score - g2d.setColor(Color.BLACK); + } + private void drawUI(Graphics2D g2d) { + g2d.setColor(new Color(83, 83, 83)); g2d.setFont(new Font("Courier New", Font.BOLD, 16)); if (hiImg != null && highScore > 0) { g2d.drawImage(hiImg, WIDTH - 200, 20, null); g2d.drawString(String.format("%05d", highScore), WIDTH - 150, 35); } g2d.drawString(String.format("%05d", score), WIDTH - 80, 35); - - // Draw game over + } + private void drawOverlays(Graphics2D g2d) { if (gameOver) { if (gameOverImg != null) { g2d.drawImage(gameOverImg, WIDTH / 2 - gameOverImg.getWidth() / 2, 100, null); @@ -365,25 +432,45 @@ public class DinoGame extends JPanel implements ActionListener, KeyListener { if (replayImg != null) { g2d.drawImage(replayImg, WIDTH / 2 - replayImg.getWidth() / 2, 150, null); } - } + g2d.setFont(new Font("Arial", Font.BOLD, 18)); + g2d.drawString("Press SPACE to restart", WIDTH / 2 - 110, 200); + } else if (!gameStarted) { + g2d.setColor(new Color(83, 83, 83)); + g2d.setFont(new Font("Arial", Font.BOLD, 24)); + String msg = "Press SPACE to Start"; + FontMetrics fm = g2d.getFontMetrics(); + int msgWidth = fm.stringWidth(msg); + g2d.drawString(msg, (WIDTH - msgWidth) / 2, HEIGHT / 2); - // Draw start message - if (!gameStarted) { - g2d.setFont(new Font("Arial", Font.BOLD, 20)); - g2d.drawString("Press SPACE to Start", WIDTH / 2 - 120, HEIGHT / 2); - } - - // Draw pause - if (paused) { - g2d.setFont(new Font("Arial", Font.BOLD, 30)); - g2d.drawString("PAUSED", WIDTH / 2 - 60, HEIGHT / 2); + g2d.setFont(new Font("Arial", Font.PLAIN, 14)); + String controls = "↓ to duck • P to pause"; + msgWidth = g2d.getFontMetrics().stringWidth(controls); + g2d.drawString(controls, (WIDTH - msgWidth) / 2, HEIGHT / 2 + 30); + } else if (paused) { + g2d.setColor(new Color(83, 83, 83)); + g2d.setFont(new Font("Arial", Font.BOLD, 36)); + String msg = "PAUSED"; + FontMetrics fm = g2d.getFontMetrics(); + int msgWidth = fm.stringWidth(msg); + g2d.drawString(msg, (WIDTH - msgWidth) / 2, HEIGHT / 2); } } + + private BufferedImage getDinoImage() { + if (gameOver) { + return dinoDead; + } else if (isJumping) { + return dinoJump; + } else if (isDucking) { + return (animFrame == 0) ? dinoDownRun1 : dinoDownRun2; + } else { + return (animFrame == 0) ? dinoRun1 : dinoRun2; + } + } @Override public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); - if (key == KeyEvent.VK_SPACE) { if (!gameStarted) { gameStarted = true; @@ -395,31 +482,29 @@ public class DinoGame extends JPanel implements ActionListener, KeyListener { playSound(jumpSound); } } - if (key == KeyEvent.VK_DOWN && !isJumping && gameStarted && !gameOver) { isDucking = true; } - - if (key == KeyEvent.VK_P && gameStarted && !gameOver) { + if (key == KeyEvent.VK_UP && !gameStarted) { + gameStarted = true; + } + if ((key == KeyEvent.VK_P || key == KeyEvent.VK_ESCAPE) && gameStarted && !gameOver) { paused = !paused; } } - @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_DOWN) { isDucking = false; } } - @Override public void keyTyped(KeyEvent e) {} - - private class Obstacle { - int x, y, width, height; + private static class Obstacle { + int x; + int y, width, height; BufferedImage img; boolean isBird; - Obstacle(int x, int y, int width, int height, BufferedImage img, boolean isBird) { this.x = x; this.y = y; @@ -429,10 +514,9 @@ public class DinoGame extends JPanel implements ActionListener, KeyListener { this.isBird = isBird; } } - - private class Cloud { - int x, y; - + private static class Cloud { + int x; + int y; Cloud(int x, int y) { this.x = x; this.y = y; @@ -440,27 +524,27 @@ public class DinoGame extends JPanel implements ActionListener, KeyListener { } public static void main(String[] args) { - try { - SwingUtilities.invokeLater(() -> { - JFrame frame = new JFrame("Chrome Dino Game"); - try { - BufferedImage icon = ImageIO.read(DinoGame.class.getResourceAsStream("/dino-jump.png")); + SwingUtilities.invokeLater(() -> { + JFrame frame = new JFrame("Java Dino Game"); + try { + InputStream iconStream = DinoGame.class.getResourceAsStream("/dino-jump.png"); + if (iconStream != null) { + BufferedImage icon = ImageIO.read(iconStream); frame.setIconImage(icon); - } catch (IOException e) { - System.err.println("Errore caricamento icona: " + e.getMessage()); - e.printStackTrace(); } - DinoGame game = new DinoGame(); - frame.add(game); - frame.pack(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setLocationRelativeTo(null); - frame.setResizable(false); - frame.setVisible(true); - }); - } catch (Exception e){ - System.err.println("Error : " + e.getMessage()); - e.printStackTrace(); - } + } catch (Exception e) { + System.err.println("Could not load icon: " + e.getMessage()); + } + + DinoGame game = new DinoGame(); + frame.add(game); + frame.pack(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); + frame.setResizable(false); + frame.setVisible(true); + + game.requestFocusInWindow(); + }); } } \ No newline at end of file