Java 贪吃蛇游戏开发记录

JavaSwing游戏循环双缓冲

用 Java Swing 从零实现贪吃蛇的过程记录——游戏循环、碰撞检测、双缓冲消除闪烁、最高分持久化。

游戏循环设计

游戏循环是整个游戏的核心驱动力。使用 javax.swing.Timer 而非自己写 while 循环——Timer 在 EDT(事件分发线程)上回调,天然与 Swing 的渲染机制同步,避免线程安全问题。

关键参数:Timer(delay, actionListener),delay 初始为 150ms,每吃 5 个食物减少 10ms,最低 60ms——实现难度递增。

数据结构选择

蛇的身体用 LinkedList<Point> 存储:

双缓冲消除闪烁

直接 paintComponent(Graphics g) 作画时,如果绘制内容多、帧率高,会出现肉眼可见的闪烁。原因:Swing 默认的绘制是直接在屏幕上逐元素绘制,用户能看到中间状态。

解决方案——双缓冲:

  1. 创建离屏 BufferedImage:new BufferedImage(width, height, TYPE_INT_ARGB)
  2. 所有绘制操作在 BufferedImage 的 Graphics 上进行
  3. 一次性将完整画面绘制到屏幕上:g.drawImage(buffer, 0, 0, null)

用户看到的是完整的每一帧,不会有半成品画面。

碰撞检测

碰撞类型检测方式
撞墙蛇头坐标 x < 0 或 x >= gridWidth 或 y < 0 或 y >= gridHeight
撞自己遍历蛇身(skip 蛇头),检查是否有坐标与蛇头重合
吃到食物蛇头坐标与食物坐标重合

最高分持久化

游戏结束时,将当前分数与历史最高分比较。历史最高分存储在本地文件中:

读取:Files.readString(Path.of("highscore.txt"))

写入:Files.writeString(Path.of("highscore.txt"), String.valueOf(newHigh))

最大收获:这个项目让我真正理解了"双缓冲"的必要性。之前看书上提到双缓冲觉得是高级技巧,直到自己写贪吃蛇看到画面疯狂闪烁,才明白为什么需要它——那一刻的顿悟比看十页书都管用。

← 返回笔记列表