Перемещение Пакмана

Это программа, которую я написал для создания pacman. Теперь я хочу, чтобы Пакман двигался по прямой линии от случайной начальной точки к случайной цели. Подскажите, пожалуйста, как это сделать.

import javax.swing.JFrame;

/**
 * Main class for pacman example. All it does is create a frame and put
 * the pacman panel in it. 
 */


    public class PacmanGUI extends JFrame{
    private Pacman pc;
        public PacmanGUI(){
        super("Pacman");
        pc = new Pacman();
        this.getContentPane().add(pc);  
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.pack();
        this.setVisible(true);
    }
        public static void main(String[] args) {
        new PacmanGUI();
    }

}

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * Pacman class that extends JPanel and paints a pacman animation.
 * It uses Timers and Actionlistener to do the Animation.
 *
 */

    public class Pacman extends JPanel implements ActionListener{
        private int figureSize = 50;
        private static final int DELAY = 200;
        private double mouthOpenPercentages[] = {.1,.5};
        private Timer animationTimer;
        private int mouthState = 0;
        private Point pacManPosition;

    /**
     * No args constructor that starts the animation.
     */
        public Pacman(){
        startAnimation();
        }

    /**
     * Overriden paintComponent method that paints pacman.
     */
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
        pacManPosition = new Point(this.getWidth()/2 - figureSize/2,
                                    this.getHeight()/2 - figureSize/2);
        g.fillRect(0,0,this.getWidth(), this.getHeight());

    drawPacMan(g);
        mouthState = (++mouthState) % mouthOpenPercentages.length;
    }
    /**
     * Stops the animation by stopping the animation timer.     
     */
    public void stopAnimation(){ animationTimer.stop(); }

    /**
     * Method do deal with actionevents that are triggered. In this
     * case we only have actionevents being triggered from our timer 
     * and by the more usual case of a button click.
     */
    public void actionPerformed(ActionEvent e){ repaint(); }

    /**
     * Gets the size that this component would like to be.
     */
    public Dimension getPreferredSize(){ return new Dimension(400,400); }

    /**
     * Gets the minimum size for this component. 
     */
    public Dimension getMinimumSize(){ return new Dimension(200,200); }

    /**
     * Starts the animation by setting a timer. When this timer goes 
     * off the actionPerformed method will be triggered, which in 
     * turn triggers the painting.
     */
    private void startAnimation(){
        if (animationTimer == null){
            mouthState = 0;
            animationTimer = new Timer(DELAY, this);
            animationTimer.start();
        } else {  //continue animating..
            if (!animationTimer.isRunning())
            animationTimer.restart();
        }
    }
    /**
     * Draws our little pacman on the given graphics canvas.
     * @param g
     */
    private void drawPacMan(Graphics g){
        Color c = g.getColor();
        g.setColor(Color.yellow);
        g.fillOval(pacManPosition.x, pacManPosition.y, figureSize, figureSize);
        //Change color back to original and draw pacman's mouth
        g.setColor(c);
        //calculate mouth offsets
        int yOffset = (int)((figureSize/2)*mouthOpenPercentages[mouthState]);
        //draw the mouth cutout.
        int x[] = {pacManPosition.x + figureSize/2, pacManPosition.x + figureSize, pacManPosition.x + figureSize};
        int y[] = {pacManPosition.y + figureSize/2, 
                   pacManPosition.y + figureSize/2 + yOffset,
                   pacManPosition.y + figureSize/2 - yOffset};
        g.fillPolygon(x, y, x.length);
    }

}

2 ответа

проблема

Вы должны управлять двумя анимациями одновременно.

Первый, который вы уже закодировали, открывает и закрывает рот Pacman.

Вторая анимация отвечает за перемещение Pacman из одного места в другое.

Решение - спрайт класс

Я предлагаю вам создать класс Sprite. Класс Sprite будет отвечать за сохранение текущей позиции спрайта, следующей позиции спрайта и скорости, с которой спрайт перемещается.

Вы бы расширили Sprite, чтобы получить один класс Pacman и класс Chaser с 4 экземплярами.

Класс Pacman

Класс Pacman будет отвечать за анимацию рта.

Chaser class

Класс Chaser будет отвечать за определение, преследовать ли Pacman или убежать от Pacman.

Свинг Советы

Вы не должны расширять компоненты Java Swing, если только вы не переопределяете один или несколько классов компонентов. Вы должны использовать компоненты Swing.

Вы всегда должны запускать свой графический интерфейс Swing в потоке диспетчеризации событий (EDT). Вы делаете это, выполняя метод invokeLater SwingUtilities.

У вас должна быть модель GUI, отдельная от ваших компонентов GUI. Три класса, которые я определил, будут частью вашей модели GUI. Вам также нужно выложить лабиринт.

Удачи с вашим проектом.

Внутри Pacman класс, вам нужно будет создать еще 2 значения для хранения начальной и конечной точек. У тебя уже есть private Point pacManPosition; объявил, поэтому я также объявил бы их как Points. Вы хотите установить pacManPosition изначально к начальной точке.

Point start = // random start point
Point end = // random end point
Point pacManPoint = new Point(start);

Теперь вы захотите определить скорость, с которой ваш Pacman будет двигаться, скажем, 2 пикселя на кадр.

int speed = 2;

Чтобы определить, на сколько нужно двигать Пакмана в каждом кадре, нам нужно сделать некоторые вычисления. Во-первых, получить расстояние от линии -

double distance = Math.sqrt(Math.pow(end.x - start.x, 2) + 
                            Math.pow(end.y - start.y, 2));

Затем мы рассчитываем, сколько кадров потребуется, чтобы пройти это расстояние со скоростью, которую мы хотим.

int totalFrames= (int)Math.round(distance / speed);

И добавить счетчик кадров -

int frame = 0;

Теперь загляните внутрь своего paintComponent метод. Прямо сейчас вы устанавливаете pacManPosition в одну и ту же точку (центр панели) каждый раз, когда она рисует. Вместо этого вы хотите обновить pacManPosition каждый кадр, пока не дойдет до конечной позиции. Вы делаете что-то подобное ниже в paintComponent где вы обновляете mouthState каждый раз, чтобы получить рот, чтобы оживить. Для анимации позиции это будет выглядеть так:

if (frame < totalFrames) {
    pacManPosition.x = start.x + frame * (end.x - start.x) / totalFrames;
    pacManPosition.y = start.y + frame * (end.y - start.y) / totalFrames;
    frame++;
}

Это только один способ сделать анимацию движения, и он предполагает несколько вещей - постоянная скорость, нет необходимости избегать препятствий, нет контроля игрока. Расчет в totalFrames не точен - он перемещает pacMan близко к конечной точке, но нет никакой гарантии, что он закончится именно там. Это также связано с частотой кадров, которая имеет недостатки. Есть много, много других способов сделать это в зависимости от ситуации.

Другие вопросы по тегам