注释很详细,直接上代码
上一篇
新增内容
1. 键盘响应监听
2. 使用定时器事件更新画板
3. 定时器事件的开始与暂停
4. 弹球小游戏的坐标逻辑判断
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class swing_test_19 {
//创建一个窗口
private Frame frame = new Frame("swing_test_19");
//桌面宽度
private int TABLE_WIDTH = 300;
//桌面高度
private int TABLE_HEIGHT = 400;
//球拍的高度和宽度
private final int RACKET_WIDTH = 60;
private final int RACKET_HEIGHT = 20;
//球的大小
private final int BALL_SIZE = 16;
//定义变量,记录小球的坐标
private int ballx = 120;
private int bally = 20;
//定义变量,记录小球在x和y方向上分别的移动速度
private int speedX = 10;
private int speedY = 5;
//定义变量,记录球拍的坐标
private int racketX = 120;
private final int racketY = 340;
//定义变量,标识当前游戏是否结束
private boolean isOver = false;
//声明一个定时器
private Timer timer;
//自定义一个类,继承canvas类,充当画布
class MyCanvas extends Canvas {
@Override
public void paint(Graphics g) {
//绘制游戏内容
if (isOver) {
//游戏结束
//画笔设置为蓝色
g.setColor(Color.BLUE);
//设置游戏字体
g.setFont(new Font("Times", Font.BOLD, 30));
//在游戏屏幕中间输出“游戏结束”
g.drawString("游戏结束", TABLE_WIDTH / 2 - 100, TABLE_HEIGHT / 2);
} else {
//游戏进行中
//绘制小球
g.setColor(Color.RED);//设置小球颜色
g.fillOval(ballx, bally, BALL_SIZE, BALL_SIZE);//绘制小球
//绘制球拍
g.setColor(Color.PINK);//设置球拍颜色
g.fillRect(racketX, racketY, RACKET_WIDTH, RACKET_HEIGHT);//绘制球拍
}
}
}
//创建绘画区
MyCanvas drawArea = new MyCanvas();
//组装视图
public void init() {
//游戏逻辑控制
//完成键盘按键对球拍坐标的移动改变
KeyListener listener = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//获取键盘按键的代码
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_LEFT) {//左键
if (racketX > 0) {
racketX -= 10;
}
} else if (keyCode == KeyEvent.VK_RIGHT) {//右键
if (racketX < TABLE_WIDTH - RACKET_WIDTH) {
racketX += 10;
}
}
}
};
//给frame和drawArea注册监听器
frame.addKeyListener(listener);
drawArea.addKeyListener(listener);
ActionListener task = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//根据边界范围,反向速度
if (ballx < 0 || ballx >= TABLE_WIDTH - BALL_SIZE) {
speedX = -speedX;
}
if (bally <= 0 || (bally > racketY - BALL_SIZE && ballx >= racketX && ballx <= racketX + RACKET_WIDTH)) {
speedY = -speedY;
}
//判断小球是否超出了球拍的范围,游戏结束
if ((ballx > racketX + RACKET_WIDTH || ballx < racketX) && bally > racketY - BALL_SIZE) {
//停止定时器
timer.stop();
isOver = true;//游戏结束
//重绘界面
drawArea.repaint();
}
//更新小球的坐标,重绘界面
ballx += speedX;
bally += speedY;
drawArea.repaint();//重绘界面
}
};
//对小球坐标的控制
timer = new Timer(100, task);
timer.start();//启动定时器
//设置drawArea的大小
drawArea.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT));
frame.add(drawArea);//将drawArea添加到frame中
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new swing_test_19().init();
}
}
效果演示: