弹球游戏

本文介绍如何将原始的使用AWT编程的简单弹球小游戏升级,通过将AWT的闪烁问题转换为Swing组件,提升用户体验。作者展示了如何利用Swing的Panel组件替代Canvas,实现更稳定且无闪烁的游戏界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用AWT编程制作简单弹球小游戏

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

public class PinBall {
    //桌面的宽度
    private final int TABLE_WIDTH = 300;
    //桌面高度
    private final int TABLE_HEIGHT = 400;
    //球拍的垂直位置
    private final int RACKET_Y = 340;

    //定义球拍的宽度、高度
    private final int RACKET_HEIGHT = 20;
    private final int RACKET_WIDTH = 60;

    //小球大小
    private final int BALL_SIZE = 16;
    private Frame f = new Frame("love you~");
    Random rand = new Random();

    //小球纵向运行速度
    private int ySpeed = 10;
    //返回一个-0.5~0.5的比率,用于控制小球的运行方向
    private double xyRate = rand.nextDouble() - 0.5;
    //小球横向运行速度
    private int xSpeed = (int)(ySpeed*xyRate*2);

    //ballX和ballY代表小球的坐标
    private int ballX = rand.nextInt(200) + 20;
    private int ballY = rand.nextInt(10) + 20;

    //racketX代表球拍的水平位置
    private int racketX = rand.nextInt(200);
    private MyCanvas tableArea = new MyCanvas();

    Timer timer;
    private int score = 0;

    //游戏是否结束的旗标
    private boolean isLose = false;

    public void init()
    {
        //设置桌面区域的最佳大小
        tableArea.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT));
        f.add(tableArea);
        //定义键盘监听器
        KeyAdapter keyProcessor = new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_LEFT)
                {
                    if(racketX > 0)
                        racketX -= 10;
                }
                if (e.getKeyCode() == KeyEvent.VK_RIGHT)
                {
                    if(racketX < TABLE_WIDTH-RACKET_WIDTH)
                        racketX += 10;
                }
            }
        };
        //增加“×”关闭
        f.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        //为窗口和tableArea对象分别添加键盘监听器
        f.addKeyListener(keyProcessor);
        tableArea.addKeyListener(keyProcessor);
        //定义每0.1秒执行一次的事件监听器
        ActionListener taskPerformer = evt ->
        {
            //如果小球碰到左右边框
            if(ballX <= 0 || ballX >= TABLE_WIDTH-BALL_SIZE)
                xSpeed=-xSpeed;
            //如果小球高度超出了球拍的位置,且横向不在球拍范围之内,则游戏结束
            if (ballY >= RACKET_Y -BALL_SIZE &&(ballX<racketX || ballX>racketX + RACKET_WIDTH))
            {
                timer.stop();
                isLose = true;
                tableArea.repaint();
            }
            //如果小球位于球拍之内, 且到达球拍位置,小球反弹
            else if (ballY <= 0 || (ballY >= RACKET_Y- BALL_SIZE && ballX> racketX&&ballX <=racketX +RACKET_WIDTH))
            {
                ySpeed=-ySpeed;
            }
            //小球坐标变化
            ballY += ySpeed;
            ballX += xSpeed;
            tableArea.repaint();
            score ++;
        };
        timer = new Timer(100, taskPerformer);
        timer.start();
        f.pack();
        f.setVisible(true);
    }

    class MyCanvas extends Canvas
    {
        //重写paint方法
        public void paint(Graphics g)
        {
            if (isLose) {
                g.setColor(new Color(255,0,0));
                g.setFont(new Font("Times", Font.BOLD, 25));
                g.drawString("游戏结束!"+score+"分" , 50, 200 );
            }
            else
            {
                g.setColor(new Color(222, 118, 222, 255));
                g.fillOval(ballX,ballY,BALL_SIZE,BALL_SIZE);
                //设置颜色,并绘制球拍
                g.setColor(new Color(80, 80, 200, 200));
                g.fillRect(racketX, RACKET_Y, RACKET_WIDTH, RACKET_HEIGHT);
            }
        }
    }

    public static void main(String[] args) {
        new PinBall().init();
    }
}
  • 运行时会有轻微的闪烁,这是因为AWT组件的绘图没有采用双缓冲技术,当重写paint()方法来绘制图形时,所有图形都是直接绘制在GUI组件上的,所以多次重新调用paint()方法进行绘制会发生闪烁现象。使用Swing组件就可避免这种闪烁,Swing组件没有提供Canvas对应的组件,使用Swing的Panel组件作为画布即可。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lanciberrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值