java - 为什么我的射弹(图像对象)不移动? Java Swing

标签 java swing user-interface jpanel keylistener

我正在尝试制作一款演示宇宙飞船射击游戏。每次我按下空格键时,我都会在 paintComponent(Graphics g) 方法中绘制一个新的射弹(Image),并调用 moveProjectile()方法。问题是 moveProjectile() 方法似乎已关闭。

MyJPanel.java

import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class MyJPanel extends JPanel implements ActionListener
{
    private static final long serialVersionUID = 1L;

    private Timer timer;
    private Image backgroundImage;
    private Image player;
    private int playerX, playerY;
    private int projectileX,projectileY;
    private Image projectileImage;
    private ArrayList<Image> projectiles = new ArrayList<Image>();

    boolean flag = false;

    public MyJPanel(Image backgroundImage, Image player,Image projectileImage)
    {
        this.backgroundImage = backgroundImage;
        this.player = player;
        this.projectileImage = projectileImage;
        this.setLayout(null);

        timer = new Timer(50, this);
        timer.start();

        this.addKeyListener(new KeyAdapter() // Listens for a keyboard event
        {
            public void keyPressed(KeyEvent e) 
            {
                if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
                {
                    flag = true;
                    moveProjectile();
                }
                repaint();
            }
        });

        // Mouse listener
        this.addMouseMotionListener(new MouseMotionListener()
        {   
            @Override
            public void mouseMoved(MouseEvent e)
            {
                playerX = e.getX();
                playerY = e.getY();
            }

            @Override
            public void mouseDragged(MouseEvent e)
            {

            }
        });
        hideMouseCursor();

        this.setFocusable(true);
        this.setVisible(true);
    } // End of JPanle constructor

    public void paintComponent(Graphics graphics)
    {
        super.paintComponent(graphics);

        graphics.drawImage(backgroundImage,0,0,this.getWidth(),this.getHeight(),null); // Draw the background
        graphics.drawImage(player,playerX,playerY,null); // Draw the player
        if (flag)
        {
            projectileX = playerX + player.getWidth(null);
            projectileY = playerY + player.getHeight(null) / 2 - 27;
            graphics.drawImage(projectileImage,projectileX,projectileY,null);
        }
    }

    public void moveProjectile()
    {
        while (projectileX < this.getWidth())
        {
            this.projectileX += 2;
            repaint();
        }
    }

    public void  hideMouseCursor() // Hides the mouse cursor
    {
        //Transparent 16 x 16 pixel cursor image.
        BufferedImage cursorbackgroundImgage = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);

        // Create a new blank cursor.
        Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(
                cursorbackgroundImgage, new Point(0, 0), "Blank Cursor");

        // Set the blank cursor to the JPanel.
        this.setCursor(blankCursor);
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) // Without the method and the repaint() the mouse listener will not work 
    {
        repaint();
    }

    public class ProjectileThread extends Thread
    {
        @Override
        public void run()
        {
            projectileX = playerX + player.getWidth(null);
            projectileY = playerY + player.getHeight(null) / 2;

        }
    }

    public static void main(String[] args)
    {
        JFrame frame = new JFrame("A Game by me");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH); // Making the frame take a full screen

        ImageIcon backgroundImageIcon = new ImageIcon("space_background_2.jpg");
        Image backgroundImgage = backgroundImageIcon.getImage();
        ImageIcon playerImageIcon = new ImageIcon("spaceship_1.png");
        Image playerImage = playerImageIcon.getImage();
        ImageIcon projectileIcon = new ImageIcon("spaceship_projectile_1.png");
        Image projectileImage = projectileIcon.getImage();  

        frame.add(new MyJPanel(backgroundImgage,playerImage,projectileImage));
        frame.setVisible(true);
    }
} // End of MyJPanel

有一些变量和方法我不使用,所以请不要介意。代码中需要注意的地方:

if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
    flag = true;
    moveProjectile();
}
repaint();

如果按空格 -> flag = true 表示

if (flag)
{
    projectileX = playerX + player.getWidth(null);
    projectileY = playerY + player.getHeight(null) / 2 - 27;
    graphics.drawImage(projectileImage,projectileX,projectileY,null);
}

绘制射弹并将其移动到右侧。问题是它从来没有移到右边。相反,它跟随由鼠标移动的宇宙飞船。

如有任何建议,我们将不胜感激。

public class ProjectileThread extends Thread
{
    public ProjectileThread(int playerX,int playerY)
    {
        projectileX = playerX + player.getWidth(null);
        projectileY = playerY + player.getHeight(null) / 2;
    }
    @Override
    public void run()
    {
        while (projectileX < getWidth())
        {
            projectileX += 2;
        }
    }
}



public void keyPressed(KeyEvent e) 
        {
            if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
            {
                ProjectileThread projectileThread = new ProjectileThread(playerX,playerY);
                projectileThread.start();
            }
            repaint();
        }

最佳答案

您的 moveProjectile 方法通过在 X 坐标上添加 2 来水平移动射弹

this.projectileX += 2;

但是,您的绘制方法会使用玩家的 X 坐标覆盖该值:

projectileX = playerX + player.getWidth(null);

因此,每次绘制射弹时,它都位于相对于玩家的同一位置。您需要先使用玩家坐标绘制弹丸,然后在不重置其 X 坐标的情况下移动它。

您有一个线程,应该在射弹发射时启动。因此,在空格键的处理程序中,启动线程并向其传递玩家坐标。这是你的起点。然后在线程的run方法中,移动弹丸并循环等待一会儿。

关于java - 为什么我的射弹(图像对象)不移动? Java Swing ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35466485/

相关文章:

安卓用户界面 : what kind of layout options are mutually exclusive?

java - 无法从加载器加载库

java - 数据库单元: Testing insert and update operations

java - 无法将 addActionListener 添加到给定类型?

user-interface - 有没有办法在不丢失 native 窗口边框的情况下舍入Delphi VCL Form

android - CollapsingToolbarLayout 问题 : overlapping UI with ToolBar

java - Websocket onMessage中的android回调接口(interface)

java - Vaadin:将枚举值绑定(bind)到组合框(ConversionException)

java - 在生成事件的源元素的父元素中居中 JoptionPaneMessageDialog

java - JFrame GUI 卡住 + Phantom