Используйте IDEA, чтобы создать объектно-ориентированную игру на Java "Forgive Hat Battle"

Отображение достижений

Вставьте описание изображения сюда

Идеи производства

Шаг 1. Откройте для себя класс (объект)

人物-小丑: Buffoon
子弹-帽子:Missile
墙体:Wall
爆炸物:Explode

Шаг 2. Откройте для себя атрибуты

小丑:宽和高,位置(x,y),移动速度
帽子:宽和高,位置(x,y),移动速度
墙体:宽和高,位置(x,y)
爆炸物:宽和高,位置(x,y)

Шаг 3. Откройте для себя метод

小丑:移动、攻击、人物撞边界
子弹:移动、子弹撞墙、子弹撞边界
爆炸物:消失

Анализ сложности

Как создать форму

public class GameClient extends Frame

Реализуйте форму Java, наследуя класс Frame

public class Frame extends Window implements MenuContainer

Класс Frame наследует класс Window и интерфейс MenuContainer.

Как загрузить картинки в форму

Шаг 1. Создайте общий инструментальный класс CommonUtils, создайте новый метод getImage для преобразования ресурсов изображения в объекты Java.

public class CommonUtils {
    
    
    /**
     * 读取图片资源, 转变为Java对象 Image
     * @param imgPath  图片路径
     * @return Image对象
     */
    public static Image getImage(String imgPath) {
    
    
        ImageIcon imageIcon = new ImageIcon(imgPath);
        return imageIcon.getImage();
    }
}

Шаг 2. Вызовите метод getImage, чтобы добавить изображение объекта

public class GameClient extends Frame {
    
    
    Image bg_image = CommonUtils.getImage("images/bg.png");
    Image explode = CommonUtils.getImage("images/explode.png");
    Image missile = CommonUtils.getImage("images/missile.png");
    Image wall_h = CommonUtils.getImage("images/wall-h.png");
    Image wall_v = CommonUtils.getImage("images/wall-v.png");
    Image buffoon = CommonUtils.getImage("images/body/s-left.png");

Шаг 3. Перепишите метод рисования Framed, чтобы реализовать форму для загрузки изображений.

@Override
    public void paint(Graphics g){
    
    
        //画背景图
        g.drawImage(bg_image,0,0,1100,700,this);
        //画小丑
        g.drawImage(buffoon,300,200,80,80,this);
        //画爆炸物
        g.drawImage(explode,800,400,90,90,this);
        //画原谅帽
        g.drawImage(missile,300,300,60,60,this);
        //画横着的墙体
        g.drawImage(wall_h,400,300,100,20,this);
        //画竖着的墙体
        g.drawImage(wall_v,400,300,20,100,this);

Метод drawImage класса Graphics должен предоставить параметр класса Image, параметр x формы, параметр y формы, ширину класса Image, длину класса Image и наблюдателя (объект, который будет уведомлен при преобразовании большего количества изображений)

Реализация движения объекта

Направление целевой карты обычно определяется правилом «вверх на север, ниже на юг, слева запад и правый восток». Восемь направлений движения обычно относятся к северу, северо-востоку, востоку, юго-востоку, югу, юго-западу, западу и северо-западу. Поэтому, определяя направление движения, используйте верхний, левый, нижний, правый, верхний правый, нижний правый, верхний левый и нижний левый угол, чтобы указать

Разработано Лин Джиабином

小丑:移动  move<Orientation类传递方向参数>
'left向左'   :x = x - this.speed;
'right向右'  :x = x + this.speed;
'down向下'   :y = y + this.speed;
'up向上'     :y = y - this.speed;
'ur东北方向'  : x = x + this.speed;
                y = y - this.speed;
'ul西北方向'  : x = x - this.speed;
                y = y - this.speed;
'dr东南方向'  : x = x + this.speed;
                y = y + this.speed;
'dl西南方向'  : x = x - this.speed;
                y = y + this.speed;

Реализация закрытия формы

    public void start() {
    
    
        //窗体添加侦听方法
        this.addWindowListener(new WindowAdapter() {
    
    
            @Override
            public void windowClosing(WindowEvent e) {
    
    
                super.windowClosing(e);
                //退出游戏
                System.exit(0);
            }
        });

Класс WindowAdapter :
1. Абстрактный класс адаптера, который получает события окна. Методы в этом классе пусты. Цель этого класса - облегчить создание объектов-слушателей.
2. Расширьте этот класс, чтобы создать слушателей WindowEvent и переопределить метод для требуемых событий. (Если вы хотите реализовать интерфейс WindowListener, вы должны определить все методы в интерфейсе. Этот абстрактный класс определяет все методы как нулевые, поэтому вам нужно только определить методы для событий, которые вас интересуют.
3. Используйте расширенные классы для создания объектов-слушателей , А затем используйте метод addWindowListener окна, чтобы зарегистрировать слушателя в окне. Когда состояние окна изменяется путем открытия, закрытия, активации или деактивации, создания значков или де-значков, будет вызван соответствующий метод в объекте прослушивателя , И передайте WindowEvent методу.
WindowAdapter listener

Реализация триггера ключевого события

 this.addKeyListener(new KeyAdapter() {
    
    
             //键盘按下的时候出发
            @Override
            public void keyPressed(KeyEvent e) {
    
    
                super.keyPressed(e);
            }
            //键盘松开
            @Override
            public void keyReleased(KeyEvent e) {
    
    
                //获取被按下的键对应的数值,如,a:67,b:68
                int keyCode = e.getKeyCode();
                switch (keyCode){
    
    
                    case KeyEvent.VK_UP:
                        System.out.println("向上走!!!");
                        buffoon.setDir("UP");
                        break;
                    case KeyEvent.VK_DOWN:
                        System.out.println("向下走");
                        buffoon.setDir("DOWN");
                        break;
                    case KeyEvent.VK_RIGHT:
                        System.out.println("向右走");
                        buffoon.setDir("RIGHT");
                        break;
                    case KeyEvent.VK_LEFT:
                        System.out.println("向左走!!");
                        buffoon.setDir("LEFT");
                        break;
                }
                buffoon.move(buffoon.getDir());
            }
        });

Ключевые моменты нажатия клавиш

Точка 1: 'new KeyAdapter ()' Создайте новый прослушиватель ключевого события и зарегистрируйте его в основной форме с помощью addKeyListener ();
Точка 2: Перепишите методы KeyAdapter, а именно KeyTyped (тип), KeyPresdded (нажмите Далее), KeyReleased (выпущен). Здесь мы слушаем только событие KeyPressed и переписываем этот метод, чтобы реализовать изменение состояния направления персонажа;
третий пункт: KeyEvent e.getKeyCode возвращает значение ключа, соответствующее нажатой клавише, обратитесь к свойству значения ключа KeyEvent. Онлайн-API Java 8

Создать объект методом Buffoon.move ()

    public void move(String dir){
    
    
        switch (dir){
    
    
            case "UP":
                this.y -= this.speed;
                setDir("STOP");
                break;
            case "DOWN":
                this.y += this.speed;
                setDir("STOP");
                break;
            case "RIGHT":
                this.x += this.speed;
                setDir("STOP");
                break;
            case "LEFT":
                this.x -= this.speed;
                setDir("STOP");
                break;
        }

Каждый раз, когда отслеживается ключевое событие, вызывается метод move для реализации движения объекта-шутовца.

Вызов метода перемещения каждый раз, когда отслеживается ключевое событие

Принцип движения объекта

Движущееся изображение объекта также называется анимацией. Оно отображает серию непрерывных анимированных изображений кадр за кадром на экране, а затем отображает следующий кадр с коротким интервалом. Это повторяется, используя «постоянство зрения» человеческого глаза. «Явление субъективно ощущается так, как будто объекты на картинке движутся.
FPS (Frames Per Second) - это количество кадров в секунду. Один кадр представляет собой статический портрет, а скорость воспроизведения видео составляет 24 кадра в секунду. Чем больше кадров, тем плавнее отображается движение. В общем, минимум, необходимый для предотвращения резких движений, составляет 30 кадров в секунду. Энциклопедия FPS Baidu

Анимированный движущийся портер-нить

Что такое поток?
Поток - это наименьший элемент, который операционная система может выполнять по расписанию. Он включен в процесс и является фактически действующей единицей в процессе. Поток относится к одному последовательному потоку управления в процессе.Множественные потоки могут быть параллельны в процессе, и каждый поток выполняет разные задачи параллельно.

/**
 * 定义一个重新绘制画面的线程,相当于招一个工人专门去从事这项工作
 */
public class RePaintThread implements Runnable{
    
    
    @Override
    //线程操作的全都在run方法中
    public void run() {
    
    
        while (true){
    
    
            //每50毫秒 执行一次
            try {
    
    
                Thread.sleep(20);
                //重新绘制图像
                gameClient.repaint();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }

Точка 1:
Открытый класс интерфейса Runnable RePaintThread реализует Runnable
При создании потока с объектом, который реализует интерфейс Runnable, запуск потока вызовет метод run объекта в независимо выполняющемся потоке.
Пункт второй: переопределить метод Run
Общий контракт метода run: он может выполнять любое желаемое действие.
Перекрасить изображение
gameClient.repaint ();
Ключевой момент 3: Thread.sleep - интервал времени между повторным выполнением потока 1. Используйте'While (
true) ', чтобы построить бесконечный цикл
2. Выполните repaint () в бесконечном цикле, чтобы перерисовать метод формы
3. Исключение прерывания потока (InterruptedException) является одним из проявлений прерывания текущего потока. Когда вы сталкиваетесь с этим исключением, если вы не знаете, как с ним справиться, вы должны выбросить его вверх.
оговорка

рекомендация

отblog.csdn.net/qq_42760141/article/details/109599610