Files
java-kursach/CarAnimation.java
2026-04-26 23:49:53 +09:00

307 lines
12 KiB
Java
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
public class CarAnimation extends JFrame {
public CarAnimation() {
setTitle("Анимация с машинкой");
setSize(1280, 720);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// панель анимации
AnimationPanel panel = new AnimationPanel();
JMenuBar menuBar = new JMenuBar();
// меню файл
JMenu fileMenu = new JMenu("Файл");
JMenuItem useFolderItem = new JMenuItem("Использовать картинки из папки");
JMenuItem exitItem = new JMenuItem("Выход");
useFolderItem.addActionListener(e -> {
JFileChooser chooser = new JFileChooser();
// только папки
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setDialogTitle("Выберите папку с изображениями машинок");
int returnVal = chooser.showOpenDialog(CarAnimation.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
// выбранная папка в панель
panel.loadImagesFromFolder(chooser.getSelectedFile());
}
});
exitItem.addActionListener(e -> System.exit(0));
fileMenu.add(useFolderItem);
fileMenu.add(exitItem);
// меню скорость
JMenu speedMenu = new JMenu("Скорость машинки");
JMenuItem slowSpeed = new JMenuItem("Медленно");
JMenuItem normalSpeed = new JMenuItem("Нормально");
JMenuItem fastSpeed = new JMenuItem("Быстро");
slowSpeed.addActionListener(e -> panel.setSpeed(100));
normalSpeed.addActionListener(e -> panel.setSpeed(50));
fastSpeed.addActionListener(e -> panel.setSpeed(20));
speedMenu.add(slowSpeed);
speedMenu.add(normalSpeed);
speedMenu.add(fastSpeed);
// меню справка
JMenu helpMenu = new JMenu("Справка");
JMenuItem aboutItem = new JMenuItem("О программе");
aboutItem.addActionListener(e -> JOptionPane.showMessageDialog(this, "Анимация машинки\nУправление: наведите мышь на окно."));
helpMenu.add(aboutItem);
// сборка менюбара
menuBar.add(fileMenu);
menuBar.add(speedMenu);
menuBar.add(helpMenu);
setJMenuBar(menuBar);
add(panel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
CarAnimation app = new CarAnimation();
app.setVisible(true);
});
}
}
class AnimationPanel extends JPanel implements MouseListener, java.awt.event.MouseMotionListener {
private final BufferedImage[] frames;
private int currentFrameIndex = 0;
private volatile boolean isMouseInside = false; // флаг для управления потоком
private final Thread animationThread;
private volatile int speedDelay = 100; // переменная для скорости
private BufferedImage[] currentFrames; // чтобы можно было менять массив картинок
private volatile boolean isFolderMode = false; // true, если загружены файлы из папки
// метод для изменения скорости
public void setSpeed(int newSpeed) {
this.speedDelay = newSpeed;
}
// метод для загрузки картинок из папки
public void loadImagesFromFolder(File folder) {
// список всех файлов в папке
File[] files = folder.listFiles();
if (files == null || files.length == 0) {
JOptionPane.showMessageDialog(this, "Папка пуста!");
return;
}
// только картинки (png, jpg, gif)
File[] imageFiles = Arrays.stream(files)
.filter(f -> f.getName().toLowerCase().endsWith(".png") ||
f.getName().toLowerCase().endsWith(".jpg") ||
f.getName().toLowerCase().endsWith(".jpeg") ||
f.getName().toLowerCase().endsWith(".gif"))
.sorted(Comparator.comparing(File::getName)) // сортировка по имени
.toArray(File[]::new);
if (imageFiles.length == 0) {
JOptionPane.showMessageDialog(this, "В выбранной папке нет подходящих изображений!");
return;
}
// найденные файлы в массив BufferedImage
BufferedImage[] newFrames = new BufferedImage[imageFiles.length];
try {
for (int i = 0; i < imageFiles.length; i++) {
newFrames[i] = ImageIO.read(imageFiles[i]);
}
// обновляем массив в панели
this.currentFrames = newFrames;
this.isFolderMode = true;
this.currentFrameIndex = 0; // Сбрасываем кадр на первый
this.repaint();
JOptionPane.showMessageDialog(this, "Загружено кадров: " + newFrames.length);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Ошибка при чтении файлов: " + e.getMessage());
e.printStackTrace();
}
}
private int carX = 0;
public AnimationPanel() {
// подготовка изображений
frames = prepareImages();
this.currentFrames = prepareImages();
// создание и запуск потока анимации
animationThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
if (carX > getWidth()) {
carX = -200; // Сбрасываем на ширину новой машинки, чтобы она выезжала плавно
}
if (isMouseInside) {
// Двигаем машинку вправо
carX += 15;
// Если машинка уехала за правый край, возвращаем её за левый край
if (carX > getWidth()) {
carX = -100;
}
// Если нужны еще и смены кадров (анимация колес и т.д.)
currentFrameIndex = (currentFrameIndex + 1) % frames.length;
repaint();
Thread.sleep(speedDelay);
} else {
Thread.sleep(50);
}
} catch (InterruptedException e) {
break;
}
}
}
});
animationThread.start();
addMouseListener(this);
addMouseMotionListener(this);
}
private BufferedImage createDummyCar(int frame, int total) {
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = img.createGraphics();
// 1. Рисуем корпус машинки
g.setColor(Color.RED);
g.fillRect(0, 40, 100, 40);
// крыша
g.setColor(Color.RED);
g.fillRect(20, 20, 60, 20);
// 2. Рисуем окна
// Цвет стекла (светло-голубой)
g.setColor(new Color(173, 216, 230));
// Переднее окно
g.fillRect(30, 25, 15, 15);
// Заднее окно
g.fillRect(55, 25, 15, 15);
// // Добавляем черную обводку для окон, чтобы они были четкими
// g.setColor(Color.BLACK);
// g.drawRect(20, 45, 25, 15);
// g.drawRect(50, 45, 25, 15);
// 3. Рисуем колеса
g.setColor(Color.BLACK);
g.fillOval(10, 70, 20, 20);
g.fillOval(70, 70, 20, 20);
g.dispose();
return img;
}
private BufferedImage[] prepareImages() {
int frameCount = 1; // количество кадров
this.isFolderMode = false;
BufferedImage[] imgArray = new BufferedImage[frameCount];
// создание болванок
for (int i = 0; i < frameCount; i++) {
imgArray[i] = createDummyCar(i, frameCount);
}
return imgArray;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (frames.length > 0) {
// 1. Параметры машинки
int originalWidth = frames[0].getWidth();
int originalHeight = frames[0].getHeight();
int newWidth = originalWidth * 2;
int newHeight = originalHeight * 2;
int x = carX;
int y = (getHeight() - newHeight) / 2;
// 2. Параметры дороги
int roadHeight = 80;
int roadY = y + newHeight - 90; // Дорога под колесами
// --- ОТРИСОВКА ФОНА (СЛОИ) ---
// Слой 1: Небо (голубое)
// Рисуем на весь экран
g.setColor(new Color(135, 206, 235)); // Цвет SkyBlue
g.fillRect(0, 0, getWidth(), getHeight());
// Слой 2: Трава (темно-зеленая)
// Рисуем от нижней границы дороги до самого низа экрана
g.setColor(new Color(34, 139, 34)); // Цвет ForestGreen
int grassStartY = roadY + roadHeight;
int grassHeight = getHeight() - grassStartY;
if (grassHeight > 0) {
g.fillRect(0, grassStartY, getWidth(), grassHeight);
}
// Слой 3: Дорога (темно-серая)
g.setColor(Color.DARK_GRAY);
g.fillRect(0, roadY, getWidth(), roadHeight);
// Слой 4: Разметка (белая)
g.setColor(Color.WHITE);
for (int i = 0; i < getWidth(); i += 60) {
g.fillRect(i, roadY + (roadHeight / 2) - 3, 30, 6);
}
// --- ОТРИСОВКА ОБЪЕКТОВ ---
// Слой 5: Машинка (поверх всего)
g.drawImage(currentFrames[currentFrameIndex], x, y, newWidth, newHeight, this);
}
if (isFolderMode) {
g.setColor(Color.BLUE);
g.drawString("Кадров в папке: " + currentFrames.length, 10, 40);
}
// подсказка
g.setColor(Color.GRAY);
g.drawString(isMouseInside ? "Статус: Анимация работает" : "Статус: Пауза (мышь снаружи)", 10, 20);
}
// Реализация методов MouseListener
@Override
public void mouseEntered(MouseEvent e) {
isMouseInside = true; // запуск
}
@Override
public void mouseExited(MouseEvent e) {
isMouseInside = false; // остановка
}
@Override public void mouseClicked(MouseEvent e) {}
@Override public void mousePressed(MouseEvent e) {}
@Override public void mouseReleased(MouseEvent e) {}
@Override public void mouseMoved(MouseEvent e) {}
@Override public void mouseDragged(MouseEvent e) {}
}