Проблемы с анимацией и движением Pacman в Java

Для анимации я использую полосу изображений pacman (рот открыт, полузакрыт, полностью закрыт), различный для каждого направления, и рисую их:

frame = 0;

public  void paintComponent(Graphics g) {
    super.paintComponent(g);    
    g.drawImage(PacRIGHT.getSubimage(frame, 0, 28, 28), x, y, null);
}  

чтобы анимировать pacman, фрейм должен быть * на 30 для перемещения на 30 пикселей вправо и>= 60 для завершения 1 цикла анимации, который будет выглядеть так:

frame = 0*30 ;
frame = 1*30 ;
frame = 2*30 ;

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


ОБНОВЛЕНИЕ: ИСПОЛЬЗУЕТСЯ таймер поворота на этот раз КОД обновлен, теперь у меня есть движущийся Пакман и анимированный рот правильного направления введите описание изображения здесь проблема сейчас я получаю несколько ошибок.

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Runtest extends JPanel implements ActionListener, KeyListener {

    Timer t = new Timer(4, this);
    int x, y, velocx, velocy = 0;
    int keyCode;
    int frame = 0;

    BufferedImage PacUP;
    BufferedImage PacDOWN;
    BufferedImage PacLEFT;
    BufferedImage PacRIGHT;

    public Runtest() throws IOException {
        t.start();
        addKeyListener(this);
        setFocusable(true);
        PacRIGHT = ImageIO.read(new File("E:\\javapacman\\newright.png"));

    }

    public int frame() {

        frame++;
        if (frame > 3)
            frame = 0;

        return frame;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(PacRIGHT.getSubimage(frame() * 30, 0, 28, 28), x, y, null);

        // Graphics2D g2 = (Graphics2D) g ;
        // g2.fill(new Ellipse2D.Double(x,y,40,40));
    }

    public void actionPerformed(ActionEvent ae) {
        repaint();
        x += velocx;
        y += velocy;
    }

    public void up() {
        velocy = -1;
        velocx = 0;

    }

    public void down() {
        velocy = 1;
        velocx = 0;

    }

    public void left() {
        velocx = -1;
        velocy = 0;

    }

    public void right() {
        velocx = 1;
        velocy = 0;
    }

    @Override
    public void keyPressed(KeyEvent ke) {
        keyCode = ke.getKeyCode();

        if (keyCode == KeyEvent.VK_UP) {
            up();
        }

        if (keyCode == KeyEvent.VK_DOWN) {
            down();
        }

        if (keyCode == KeyEvent.VK_LEFT) {
            left();

        }
        if (keyCode == KeyEvent.VK_RIGHT) {
            right();
        }

    }
}

И основной класс:

public class PacMan {
    public static void main(String[] args) throws IOException {
        JFrame frame = new JFrame("Test");
         Runtest test = new Runtest();
         frame.setSize(400, 400);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.add(test);
         frame.setVisible(true);
    }
}    

Я получаю ошибки

Exception in thread "AWT-EventQueue-0" java.lang.UnsupportedOperationException:      Not supported yet.
at pactest.Runtest.keyReleased(Runtest.java:128)
at java.awt.Component.processKeyEvent(Component.java:6466)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2828)
at java.awt.Component.processEvent(Component.java:6282)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1895)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:762)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1027)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:899)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:727)
at java.awt.Component.dispatchEventImpl(Component.java:4731)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:708)
at java.awt.EventQueue$4.run(EventQueue.java:706)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

1 ответ

Прежде всего, на вашем месте я бы разделил движение и анимацию. Получите движение, работающее сначала с одним установленным изображением

Движение:
На ключевых событиях вы меняете параметры скорости, это кажется хорошим. Кажется, что вы используете x а также y переменные в MyPanel в качестве переменных положения. Вы должны установить их в начальное значение где-нибудь - либо в конструкторе, либо в объявлении переменной экземпляра.

У вас есть правильная идея об изменении x а также y переменные с переменными скорости, но вы делаете это в actionPerformed метод. Это не то, что вы хотите. Вам необходимо обновлять переменные положения в зависимости от времени, а не от ввода пользователя. Вы должны посмотреть на игровые циклы, как упомянуто @ug_. Игровой цикл - это, по сути, цикл, который работает в вашей игре и который непрерывно проверяет ввод, обновляет информацию об игре и отображает изменения. Вам следует обновить переменную позиции в игровом цикле. Обязательно позвони repaint после изменения переменных положения, чтобы экран отражал изменения.

Как только вы обновляете переменную позиции правильно, вам нужно использовать те x а также y переменные в качестве параметров положения в вашем paintComponent метод при вызове g.drawImage, Таким образом, положение изображения рисуется там, где вы отслеживаете x а также y,

Анимация:
Как только у вас будет работать движение, вы должны выяснить переключение изображения. Предложение для этого будет иметь переменную экземпляра curImage что твой g.drawImage вызов использует. Затем вы будете использовать свой "игровой цикл" для управления циклом по 3 изображениям, чтобы выбрать, какое изображение установить в качестве curImage, Это будет зависеть от времени, поэтому, например, каждые 1/2 секунды вы можете изменить изображение на следующее в коллекции. Когда вы доберетесь до конца коллекции, вы переместитесь в обратном направлении через коллекцию. Так что порядок будет: open, half, close, half, open, half, etc.., Вы также можете легко сделать это с помощью счетчика индексов, который изначально был установлен в 0, увеличивается каждый раз при выборе изображения, а затем уменьшается при достижении конечного изображения в коллекции, повторите процесс, когда вернетесь к началу.

Также вы упомянули, что у вас есть разные наборы изображений для каждого направления. В игровом цикле вы можете проверить параметры скорости, чтобы определить направление движения. Эта информация скажет вам, из какой коллекции изображений вытащить изображения. Затем вы можете использовать счетчик индекса, чтобы получить нужное изображение из этой коллекции.

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