如何在JPanel上绘制不同类图形?Pong游戏 paddle绘制问题求助
解决你的Pong游戏HumanPaddle绘制问题
嘿,我看了你的代码,问题其实很明确——你的HumanPaddle根本没被绘制到界面上,而且还有几个小问题会影响游戏运行,我一步步给你拆解解决:
核心问题:Paddle没有被实例化和调用绘制
你在主类里声明了HumanPaddle player1;,但从来没有创建它的实例(也就是没写player1 = new HumanPaddle();),而且也没有在paint方法里调用player1.draw(g),所以就算paddle的代码写对了,也不会显示出来。
其他需要修复的问题
- 主线程阻塞:你写的
for (int i = 0; i < 1;)死循环在主线程里运行,会导致Swing UI完全卡住,应该用javax.swing.Timer来处理游戏循环,这是Swing推荐的方式。 - 按键监听未实现:你的
HumanPaddle有上下加速的逻辑,但主类没有实现KeyListener,也没给窗口注册监听器,所以没法控制paddle移动。 - 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; } }
修复说明
- 实例化Paddle:在主类的构造方法里创建了
player1 = new HumanPaddle(1);,并在paint方法里调用player1.draw(g),这样paddle就会被绘制出来。 - Swing Timer:用
Timer代替了死循环,保证游戏逻辑在UI线程的事件队列中执行,避免卡顿。 - 按键监听:主类实现了
KeyListener,注册了监听器,并且给HumanPaddle添加了设置加速状态的方法,现在按W/S键可以控制paddle上下移动。 - Paddle移动逻辑:修改了
HumanPaddle的draw方法使用自身属性,添加了move方法处理移动和边界限制,让paddle可以正常移动。
现在运行代码,你应该能看到红色的paddle在右侧,按W/S可以移动,小球也会正常反弹啦!
内容的提问来源于stack exchange,提问作者guy43535453
相关产品推荐
相关产品推荐

