Вопрос или проблема
У меня есть игра на Java (.jar), но когда я ее запускаю, она работает не плавно. Очень сильно лагает.
Игра по сути такая, и очень простая, но если вы запустите эту игру (по крайней мере, в моем случае), она будет иметь сбои, из-за которых в нее очень трудно играть. Я создал эту игру в 2023 году на Windows и мог нормально ее тестировать. Недавно я скачал Ubuntu, и я не уверен, делаю ли я что-то неправильно
Вот код игры, если кто-то программист:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import java.util.Set;
import java.util.HashSet;
import javax.sound.sampled.*;
public class Main extends JFrame {
ImageIcon icon = new ImageIcon(getClass().getClassLoader().getResource("logogame.png"));
int comeu = 0;
int x = 200;
int y = 100;
Set<Integer> keys = new HashSet<>();
int speed = 5;
Circle circle;
public Main() {
JMenuBar barramenu = new JMenuBar();
JMenu menu = new JMenu("Menu");
JMenuItem sobre = new JMenuItem("Sobre");
JMenuItem sair = new JMenuItem("Sair");
setJMenuBar(barramenu);
barramenu.add(menu);
menu.add(sobre);
menu.add(new JSeparator());
menu.add(sair);
sobre.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Primeiro jogo puro criado em java por Cabralito em 2023");
}
});
sair.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
setTitle("Square and Circle (2023)");
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setSize(400, 400);
setLocationRelativeTo(null);
getContentPane().setBackground(Color.black);
getContentPane().add(new Cavar());
setIconImage(icon.getImage());
circle = generateRandomCircle();
Timer timer = new Timer(10, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (keys.contains(KeyEvent.VK_A)) {
x -= speed;
}
if (keys.contains(KeyEvent.VK_D)) {
x += speed;
}
if (keys.contains(KeyEvent.VK_W)) {
y -= speed;
}
if (keys.contains(KeyEvent.VK_S)) {
y += speed;
}
checkCollision();
repaint();
}
});
timer.start();
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
keys.add(e.getKeyCode());
}
@Override
public void keyReleased(KeyEvent e) {
keys.remove(e.getKeyCode());
}
});
setFocusable(true);
requestFocusInWindow();
}
public void playSound(String soundFileName) {
try {
ClassLoader classLoader = getClass().getClassLoader();
InputStream audioIn = classLoader.getResourceAsStream(soundFileName);
if (audioIn == null) {
throw new IOException("Arquivo de áudio não encontrado: " + soundFileName);
}
byte[] audioData = audioIn.readAllBytes();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(audioData);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(byteArrayInputStream);
Clip clip = AudioSystem.getClip();
clip.open(audioStream);
clip.start();
} catch (Exception e) {
e.printStackTrace();
}
}
class Cavar extends JComponent {
public void paint(Graphics g) {
g.setColor(Color.RED);
g.fill3DRect(x, y, 50, 50, true);
if (circle != null && circle.isVisible()) {
g.setColor(Color.GREEN);
g.fillOval(circle.getX() - circle.getRadius(), circle.getY() - circle.getRadius(), circle.getRadius(), circle.getRadius());
}
g.setColor(Color.WHITE);
g.drawString("Comeu: " + comeu, 10, 20);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new Main();
});
}
class Circle {
private int x;
private int y;
private int radius;
private boolean visible;
public Circle(int x, int y, int radius, boolean visible) {
this.x = x;
this.y = y;
this.radius = radius;
this.visible = visible;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getRadius() {
return radius;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
}
private Circle generateRandomCircle() {
Random random = new Random();
int circleX;
int circleY;
do {
circleX = random.nextInt(getWidth() - 50);
circleY = random.nextInt(getHeight() - 50);
} while (Math.abs(circleX - x) < 50 && Math.abs(circleY - y) < 50);
return new Circle(circleX, circleY, 25, true);
}
private void checkCollision() {
if (circle.isVisible() && Math.abs(x - circle.getX()) < 50 && Math.abs(y - circle.getY()) < 50) {
circle.setVisible(false);
circle = generateRandomCircle();
comeu++;
playSound("som/Dingw.wav");
}
}
}
Ответ или решение
Чтобы обеспечить стабильную работу программы Java (.jar) без падений и лагов, особенно если она испытывает проблемы при запуске на Ubuntu после разработки в Windows, следует рассмотреть ряд аспектов, начиная от кода и заканчивая средой выполнения. Давайте разберём ключевые шаги, которые могут помочь решить проблему.
Анализ и оптимизация кода
-
Проверка использования ресурсов.
Внимательно изучите использование ресурсов в вашем коде. В вашей программе создаётся объектClip
для воспроизведения звука при каждом столкновении. Убедитесь, что этот объект корректно закрывается после завершения воспроизведения (методclip.close()
). Это предотвратит утечки ресурсов. -
Оптимизация графического интерфейса.
Методrepaint()
вызывается очень часто из таймера с интервалом в 10 миллисекунд. Это может вызывать нагрузку, особенно на слабых системах. Рассмотрите возможность увеличения интервала или оптимизации методаpaint
. Например, используйте двойную буферизацию, чтобы уменьшить мерцание и повысить производительность отрисовки. -
Устранение проблем с кодировкой потоков.
При загрузке аудио файлов или изображений убедитесь, что пути к этим ресурсам корректны и поддерживаются во всех операционных системах. Путь к "som/Dingw.wav" должен быть проверен на наличие в структуре проекта.
Оптимизация исполнения в среде Linux (Ubuntu)
-
Проверка Java Runtime Environment (JRE).
Убедитесь, что на Ubuntu установлена актуальная версия JRE, соответствующая вашей версии Java. Можно использоватьjava -version
для проверки версии Java. -
Использование параметров JVM.
Если игре не хватает памяти, увеличьте выделение памяти для JVM. Это можно сделать через параметры запуска VM, например:java -Xms256m -Xmx512m -jar yourgame.jar
. -
Проверка производительности графической подсистемы.
Убедитесь, что на Ubuntu установлены актуальные драйвера для вашей видеокарты. Это особенно важно, если игра использует графику и рендеринг. -
Обработка событий.
Проверьте, корректно ли обрабатываются события клавиатуры и окна. Убедитесь, что методsetFocusable(true)
и вызовrequestFocusInWindow()
правильно применяются для обеспечения ввода с клавиатуры.
Общие рекомендации
-
Логирование и дебаггинг.
Добавьте логирование для отслеживания выполнения программы и обнаружения узких мест. Информация о том, на каком этапе происходит сбой, поможет скорейшему обнаружению и устранению проблемы. -
Кроссплатформенное тестирование.
Протестируйте вашу программу в разных средах исполнения (Windows, Linux) с использованием различных JDK/JRE. Это поможет идентифицировать платформозависимые проблемы.
Эти шаги помогут улучшить производительность и стабильность вашего Java-приложения как на Ubuntu, так и на Windows. Оптимизация каждого из аспектов значительно увеличит общую плавность и надёжность работы программы.