<think>我们将使用Java Swing库来创建一个简单的篮球投篮小游戏。游戏的基本功能包括:
1. 玩家控制一个篮筐左右移动(通过键盘左右箭头键)。
2. 篮球从屏幕上方落下,玩家需要移动篮筐接住篮球。
3. 每接住一个篮球得一分,如果篮球落到屏幕底部则游戏结束。
游戏设计:
- 游戏窗口:600x800像素
- 篮筐:一个矩形,可以左右移动
- 篮球:一个圆形,从顶部随机位置下落
我们将使用一个线程来更新游戏状态(篮球下落)和重绘界面。
步骤:
1. 创建主窗口(JFrame)
2. 创建游戏面板(JPanel),并在其上绘制篮筐和篮球
3. 实现键盘监听,使篮筐可以左右移动
4. 实现篮球的下落逻辑,以及碰撞检测(篮球与篮筐)
5. 计分和游戏结束逻辑
代码结构:
- 主类:BasketballGame,包含main方法
- 游戏面板:GamePanel,继承JPanel,实现Runnable接口
- 在GamePanel中:
定义篮筐的位置、大小
篮球的位置、大小和下落速度
游戏循环(线程)控制篮球下落
键盘事件监听
绘制图形
注意:为了简化,我们使用矩形表示篮筐,圆形表示篮球。
代码实现如下:
</think>
# Java篮球投篮小游戏
下面是一个使用Java Swing实现的篮球投篮小游戏。玩家可以使用鼠标控制投篮方向和力度,将篮球投入篮筐得分。
```java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Random;
public class BasketballGame extends JFrame {
private GamePanel gamePanel;
public BasketballGame() {
setTitle("篮球投篮小游戏");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
setResizable(false);
setLocationRelativeTo(null);
gamePanel = new GamePanel();
add(gamePanel);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new BasketballGame());
}
}
class GamePanel extends JPanel implements MouseListener, MouseMotionListener, ActionListener {
private int ballX = 100, ballY = 400; // 篮球初始位置
private int targetX = 600, targetY = 100; // 篮筐位置
private int power = 0, maxPower = 100; // 投篮力度
private double angle = Math.PI / 4; // 投篮角度(弧度)
private boolean aiming = false, shooting = false;
private int score = 0;
private int attempts = 0;
private Timer timer;
private double ballVelocityX, ballVelocityY;
private double gravity = 0.2;
private boolean ballInAir = false;
private ArrayList<Point> trajectory = new ArrayList<>();
private Random random = new Random();
public GamePanel() {
setBackground(new Color(135, 206, 235)); // 天空蓝背景
addMouseListener(this);
addMouseMotionListener(this);
setFocusable(true);
timer = new Timer(20, this);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 绘制背景
drawBackground(g2d);
// 绘制篮筐
drawBasket(g2d);
// 绘制篮球
drawBall(g2d);
// 绘制瞄准线
if (aiming && !shooting) {
drawAimingLine(g2d);
}
// 绘制轨迹
if (!trajectory.isEmpty()) {
drawTrajectory(g2d);
}
// 绘制UI
drawUI(g2d);
}
private void drawBackground(Graphics2D g2d) {
// 绘制地板
g2d.setColor(new Color(34, 139, 34)); // 草地绿
g2d.fillRect(0, getHeight() - 100, getWidth(), 100);
// 绘制篮球场线
g2d.setColor(Color.WHITE);
g2d.setStroke(new BasicStroke(3));
g2d.drawLine(0, getHeight() - 100, getWidth(), getHeight() - 100);
// 绘制观众
g2d.setColor(new Color(50, 50, 50));
for (int i = 0; i < 20; i++) {
int x = random.nextInt(getWidth());
int y = random.nextInt(getHeight() - 200);
g2d.fillOval(x, y, 4, 4);
}
}
private void drawBasket(Graphics2D g2d) {
// 篮筐支柱
g2d.setColor(new Color(139, 69, 19)); // 棕色
g2d.fillRect(targetX - 5, targetY, 10, 50);
// 篮筐
g2d.setColor(new Color(184, 134, 11)); // 金色
g2d.setStroke(new BasicStroke(3));
g2d.drawLine(targetX - 40, targetY, targetX + 40, targetY);
g2d.drawLine(targetX - 40, targetY, targetX - 40, targetY + 10);
g2d.drawLine(targetX + 40, targetY, targetX + 40, targetY + 10);
// 篮网
g2d.setColor(Color.WHITE);
for (int i = 0; i < 6; i++) {
int y = targetY + 10 + i * 5;
int startX = targetX - 35 + i * 3;
int endX = targetX + 35 - i * 3;
g2d.drawLine(startX, y, endX, y);
}
}
private void drawBall(Graphics2D g2d) {
// 篮球
g2d.setColor(new Color(205, 133, 63)); // 棕色
Ellipse2D ball = new Ellipse2D.Double(ballX - 15, ballY - 15, 30, 30);
g2d.fill(ball);
// 篮球纹理
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(2));
g2d.drawLine(ballX, ballY - 10, ballX, ballY + 10);
g2d.drawLine(ballX - 10, ballY, ballX + 10, ballY);
g2d.drawArc(ballX - 8, ballY - 8, 16, 16, 0, 360);
}
private void drawAimingLine(Graphics2D g2d) {
g2d.setColor(new Color(255, 0, 0, 150));
g2d.setStroke(new BasicStroke(2));
int endX = ballX + (int)(Math.cos(angle) * power);
int endY = ballY - (int)(Math.sin(angle) * power);
g2d.drawLine(ballX, ballY, endX, endY);
// 绘制力度条
g2d.setColor(new Color(0, 0, 255, 100));
g2d.fillRect(20, 20, maxPower, 20);
g2d.setColor(Color.BLUE);
g2d.fillRect(20, 20, power, 20);
g2d.setColor(Color.BLACK);
g2d.drawRect(20, 20, maxPower, 20);
g2d.drawString("力度: " + power + "/" + maxPower, 25, 35);
}
private void drawTrajectory(Graphics2D g2d) {
g2d.setColor(new Color(255, 255, 255, 150));
g2d.setStroke(new BasicStroke(2));
for (int i = 1; i < trajectory.size(); i++) {
Point p1 = trajectory.get(i-1);
Point p2 = trajectory.get(i);
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
}
}
private void drawUI(Graphics2D g2d) {
// 绘制分数
g2d.setColor(Color.BLACK);
g2d.setFont(new Font("Arial", Font.BOLD, 20));
g2d.drawString("得分: " + score, getWidth() - 120, 30);
g2d.drawString("投篮次数: " + attempts, getWidth() - 120, 60);
// 绘制游戏说明
g2d.setFont(new Font("Arial", Font.PLAIN, 14));
g2d.drawString("游戏说明:", 20, getHeight() - 70);
g2d.drawString("1. 鼠标拖动设置投篮方向和力度", 20, getHeight() - 50);
g2d.drawString("2. 松开鼠标进行投篮", 20, getHeight() - 30);
// 如果游戏结束,显示消息
if (attempts >= 10) {
g2d.setColor(new Color(0, 0, 0, 200));
g2d.fillRect(getWidth()/2 - 150, getHeight()/2 - 60, 300, 120);
g2d.setColor(Color.WHITE);
g2d.setFont(new Font("Arial", Font.BOLD, 24));
g2d.drawString("游戏结束!", getWidth()/2 - 60, getHeight()/2 - 20);
g2d.setFont(new Font("Arial", Font.PLAIN, 18));
g2d.drawString("最终得分: " + score, getWidth()/2 - 50, getHeight()/2 + 10);
g2d.drawString("按R键重新开始", getWidth()/2 - 70, getHeight()/2 + 40);
}
}
@Override
public void mousePressed(MouseEvent e) {
if (ballInAir || attempts >= 10) return;
// 检查是否点击了篮球
if (Math.sqrt(Math.pow(e.getX() - ballX, 2) + Math.pow(e.getY() - ballY, 2)) <= 15) {
aiming = true;
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (aiming && !ballInAir && attempts < 10) {
shooting = true;
ballInAir = true;
trajectory.clear();
trajectory.add(new Point(ballX, ballY));
// 设置篮球初速度
ballVelocityX = Math.cos(angle) * power / 5;
ballVelocityY = -Math.sin(angle) * power / 5;
attempts++;
timer.start();
}
aiming = false;
}
@Override
public void mouseDragged(MouseEvent e) {
if (aiming) {
int dx = e.getX() - ballX;
int dy = ballY - e.getY(); // Y轴方向相反
// 计算角度
angle = Math.atan2(dy, dx);
if (angle < 0) angle += 2 * Math.PI;
// 计算力度(最大为maxPower)
power = (int) Math.min(Math.sqrt(dx*dx + dy*dy), maxPower);
repaint();
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (shooting) {
// 更新篮球位置
ballX += ballVelocityX;
ballY += ballVelocityY;
ballVelocityY += gravity; // 重力加速度
// 记录轨迹点
if (trajectory.size() < 100) { // 限制轨迹点数量
trajectory.add(new Point(ballX, ballY));
}
// 检测是否碰到边界
if (ballX < 15 || ballX > getWidth() - 15) {
ballVelocityX = -ballVelocityX * 0.8; // 反弹并损失能量
}
// 检测是否落地
if (ballY > getHeight() - 115) {
ballY = getHeight() - 115;
ballVelocityY = -ballVelocityY * 0.6; // 反弹
ballVelocityX *= 0.8; // 摩擦减速
// 如果速度很小,停止
if (Math.abs(ballVelocityY) < 1 && Math.abs(ballVelocityX) < 1) {
resetBall();
}
}
// 检测是否进球
if (ballY <= targetY + 10 && ballY >= targetY - 10) {
if (ballX >= targetX - 40 && ballX <= targetX + 40) {
score += 2;
JOptionPane.showMessageDialog(this, "进球得分! +2分", "得分", JOptionPane.INFORMATION_MESSAGE);
resetBall();
}
}
repaint();
}
}
private void resetBall() {
shooting = false;
ballInAir = false;
timer.stop();
ballX = 100;
ballY = 400;
power = 0;
trajectory.clear();
// 如果达到10次投篮,结束游戏
if (attempts >= 10) {
repaint();
}
}
@Override
public void mouseMoved(MouseEvent e) {}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
// 添加键盘监听以支持重新开始
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_R && attempts >= 10) {
score = 0;
attempts = 0;
resetBall();
repaint();
}
}
}
```
## 游戏说明
这个篮球投篮小游戏具有以下功能:
1. **游戏目标**:将篮球投入篮筐得分
2. **控制方式**:
- 鼠标拖动篮球设置投篮方向和力度
- 松开鼠标进行投篮
- 游戏结束后按R键重新开始
3. **游戏规则**:
- 每投进一球得2分
- 玩家有10次投篮机会
- 游戏结束后显示最终得分
## 代码结构解析
1. **游戏界面**:
- 使用Swing组件创建800x600像素的游戏窗口
- 自定义GamePanel处理游戏绘制和逻辑
2. **物理引擎**:
- 实现简单的抛物线运动物理模型
- 包含重力加速度和碰撞反弹效果
- 模拟篮球的弹跳特性
3. **游戏元素**:
- 篮球:圆形物体,可被拖动和投射
- 篮筐:包含篮网和支架的完整篮筐
- 背景:包含篮球场地板和观众
4. **游戏逻辑**:
- 瞄准系统:显示方向和力度
- 投篮轨迹:绘制篮球飞行路径
- 计分系统:记录得分和投篮次数
- 游戏结束:10次投篮后显示最终得分
5. **用户交互**:
- 鼠标事件处理:拖动、释放
- 键盘事件:R键重新开始游戏
## 运行说明
1. 将代码保存为BasketballGame.java
2. 使用Java编译器编译:`javac BasketballGame.java`
3. 运行游戏:`java BasketballGame`
4. 使用鼠标拖动篮球设置投篮方向和力度,松开鼠标投篮