You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JPanel上绘制不同类图形?Pong游戏 paddle绘制问题求助

解决你的Pong游戏HumanPaddle绘制问题

嘿,我看了你的代码,问题其实很明确——你的HumanPaddle根本没被绘制到界面上,而且还有几个小问题会影响游戏运行,我一步步给你拆解解决:

核心问题:Paddle没有被实例化和调用绘制

你在主类里声明了HumanPaddle player1;,但从来没有创建它的实例(也就是没写player1 = new HumanPaddle();),而且也没有在paint方法里调用player1.draw(g),所以就算paddle的代码写对了,也不会显示出来。

其他需要修复的问题

  1. 主线程阻塞:你写的for (int i = 0; i < 1;)死循环在主线程里运行,会导致Swing UI完全卡住,应该用javax.swing.Timer来处理游戏循环,这是Swing推荐的方式。
  2. 按键监听未实现:你的HumanPaddle有上下加速的逻辑,但主类没有实现KeyListener,也没给窗口注册监听器,所以没法控制paddle移动。
  3. Paddle绘制固定位置:HumanPaddle的draw方法用了固定的800,300坐标,应该用类自身的x和y属性,这样才能通过逻辑移动。

修改后的完整代码

主类 EOYPongV4

package eoypongv4;

import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.Timer;

public class EOYPongV4 extends JPanel implements KeyListener {
    int x = 0;
    int y = 0;
    boolean isballdown = true;
    boolean isballright = true;
    HumanPaddle player1;

    public EOYPongV4() {
        // 实例化玩家1的 paddle
        player1 = new HumanPaddle(1);
        // 注册按键监听器
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);

        // 用Swing Timer实现游戏循环,每10ms触发一次
        Timer gameTimer = new Timer(10, e -> {
            ballMovement();
            player1.move();
            repaint();
        });
        gameTimer.start();
    }

    private void ballMovement() {
        if (isballright) {
            x++;
        } else {
            x--;
        }
        if (isballdown) {
            y++;
        } else {
            y--;
        }

        // 边界碰撞检测
        if (y == getHeight() - 20) {
            isballdown = false;
        }
        if (y == 0) {
            isballdown = true;
        }
        if (x == getWidth() - 20) {
            isballright = false;
        }
        if (x == 0) {
            isballright = true;
        }
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillOval(x, y, 20, 20);
        // 调用paddle的绘制方法
        player1.draw(g);
    }

    // 按键监听实现
    @Override
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_W) {
            player1.setUpAccel(true);
        }
        if (key == KeyEvent.VK_S) {
            player1.setDownAccel(true);
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_W) {
            player1.setUpAccel(false);
        }
        if (key == KeyEvent.VK_S) {
            player1.setDownAccel(false);
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    public static void main(String[] args) {
        JFrame frame = new JFrame("EoyPongV4");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1068, 720);
        EOYPongV4 pong = new EOYPongV4();
        frame.add(pong);
        frame.setVisible(true);
    }
}

HumanPaddle 类

package eoypongv4;

import java.awt.Color;
import java.awt.Graphics;

public class HumanPaddle {
    double y;
    double yVel;
    boolean upAccel;
    boolean downAccel;
    int x;
    final int WIDTH = 20;
    final int HEIGHT = 80;

    public HumanPaddle(int player) {
        y = 300;
        yVel = 0;
        // 根据玩家设置初始x坐标
        if (player == 1) {
            x = 800;
        } else {
            x = 50; // 可以给玩家2留个位置
        }
        upAccel = false;
        downAccel = false;
    }

    public void move() {
        // 控制paddle的移动速度和边界
        if (upAccel) {
            yVel -= 0.5;
        } else if (downAccel) {
            yVel += 0.5;
        } else {
            // 没有按键时减速
            yVel *= 0.9;
        }

        // 限制最大速度
        if (yVel > 5) {
            yVel = 5;
        }
        if (yVel < -5) {
            yVel = -5;
        }

        y += yVel;

        // 防止paddle超出窗口边界
        if (y < 0) {
            y = 0;
        }
        if (y > 720 - HEIGHT) { // 720是窗口高度,减去paddle高度
            y = 720 - HEIGHT;
        }
    }

    public void draw(Graphics g) {
        g.setColor(Color.red);
        // 使用类自身的x、y属性绘制
        g.fillRect(x, (int) y, WIDTH, HEIGHT);
    }

    // 提供设置加速状态的方法
    public void setUpAccel(boolean upAccel) {
        this.upAccel = upAccel;
    }

    public void setDownAccel(boolean downAccel) {
        this.downAccel = downAccel;
    }
}

修复说明

  1. 实例化Paddle:在主类的构造方法里创建了player1 = new HumanPaddle(1);,并在paint方法里调用player1.draw(g),这样paddle就会被绘制出来。
  2. Swing Timer:用Timer代替了死循环,保证游戏逻辑在UI线程的事件队列中执行,避免卡顿。
  3. 按键监听:主类实现了KeyListener,注册了监听器,并且给HumanPaddle添加了设置加速状态的方法,现在按W/S键可以控制paddle上下移动。
  4. Paddle移动逻辑:修改了HumanPaddle的draw方法使用自身属性,添加了move方法处理移动和边界限制,让paddle可以正常移动。

现在运行代码,你应该能看到红色的paddle在右侧,按W/S可以移动,小球也会正常反弹啦!

内容的提问来源于stack exchange,提问作者guy43535453

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:42:47