parent
b0fb4761c6
commit
1f2a49e92d
@ -0,0 +1,130 @@
|
||||
package com.snakegame;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.util.LinkedList;
|
||||
import java.awt.event.KeyEvent; // 导入 KeyEvent
|
||||
|
||||
public class Snake {
|
||||
private final LinkedList<Point> body = new LinkedList<>();
|
||||
private final Color[] colors;
|
||||
private final boolean gradientEnabled;
|
||||
private Direction direction = Direction.RIGHT;
|
||||
private Direction nextDirection = Direction.RIGHT;
|
||||
|
||||
// 方向枚举
|
||||
private enum Direction {
|
||||
UP(0, -1),
|
||||
DOWN(0, 1),
|
||||
LEFT(-1, 0),
|
||||
RIGHT(1, 0);
|
||||
|
||||
public final int dx;
|
||||
public final int dy;
|
||||
|
||||
Direction(int dx, int dy) {
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
}
|
||||
}
|
||||
|
||||
// 构造函数
|
||||
public Snake(int x, int y, Color[] colors, boolean gradientEnabled) {
|
||||
if (colors.length < 2) throw new IllegalArgumentException("需要至少2个颜色");
|
||||
this.colors = colors.clone();
|
||||
this.gradientEnabled = gradientEnabled;
|
||||
reset(x, y);
|
||||
}
|
||||
|
||||
// 重置位置
|
||||
private void reset(int x, int y) {
|
||||
body.clear();
|
||||
body.add(new Point(x, y));
|
||||
body.add(new Point(x - 1, y));
|
||||
body.add(new Point(x - 2, y));
|
||||
}
|
||||
|
||||
// 移动逻辑
|
||||
public void move() {
|
||||
direction = nextDirection;
|
||||
Point newHead = new Point(
|
||||
body.getFirst().x + direction.dx,
|
||||
body.getFirst().y + direction.dy
|
||||
);
|
||||
body.addFirst(newHead);
|
||||
body.removeLast();
|
||||
}
|
||||
|
||||
// 身体增长
|
||||
public void grow() {
|
||||
body.addLast(new Point(body.getLast()));
|
||||
}
|
||||
|
||||
// 按键处理
|
||||
public void handleKeyPress(int keyCode) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.VK_UP:
|
||||
if (direction != Direction.DOWN) nextDirection = Direction.UP;
|
||||
break;
|
||||
case KeyEvent.VK_DOWN:
|
||||
if (direction != Direction.UP) nextDirection = Direction.DOWN;
|
||||
break;
|
||||
case KeyEvent.VK_LEFT:
|
||||
if (direction != Direction.RIGHT) nextDirection = Direction.LEFT;
|
||||
break;
|
||||
case KeyEvent.VK_RIGHT:
|
||||
if (direction != Direction.LEFT) nextDirection = Direction.RIGHT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制逻辑
|
||||
public void draw(Graphics g, int tileSize) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
for (int i = 0; i < body.size(); i++) {
|
||||
Point p = body.get(i);
|
||||
g2d.setColor(getSegmentColor(i));
|
||||
if (i == 0) {
|
||||
// 绘制蛇头(三角形)
|
||||
drawSnakeHead(g2d, p.x * tileSize, p.y * tileSize, tileSize);
|
||||
} else {
|
||||
// 绘制蛇身(圆形)
|
||||
g2d.fillOval(p.x * tileSize, p.y * tileSize, tileSize - 2, tileSize - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawSnakeHead(Graphics2D g2d, int x, int y, int tileSize) {
|
||||
GeneralPath path = new GeneralPath();
|
||||
int headSize = tileSize / 2;
|
||||
path.moveTo(x + tileSize / 2, y);
|
||||
path.lineTo(x + tileSize / 2 - headSize, y + headSize);
|
||||
path.lineTo(x + tileSize / 2 + headSize, y + headSize);
|
||||
path.closePath();
|
||||
g2d.fill(path);
|
||||
}
|
||||
|
||||
private Color getSegmentColor(int index) {
|
||||
// 头部颜色(使用数组第一个元素)
|
||||
if (index == 0) return colors[0];
|
||||
|
||||
// 未启用渐变时(使用数组第二个元素)
|
||||
if (!gradientEnabled) return colors[1];
|
||||
|
||||
// 渐变计算(从第二个颜色渐变到第一个颜色)
|
||||
Color startColor = colors[1]; // 身体基础色
|
||||
Color endColor = colors[0]; // 头部颜色
|
||||
float ratio = (float) (index - 1) / (body.size() - 1);
|
||||
|
||||
return new Color(
|
||||
(int) (startColor.getRed() * (1 - ratio) + endColor.getRed() * ratio),
|
||||
(int) (startColor.getGreen() * (1 - ratio) + endColor.getGreen() * ratio),
|
||||
(int) (startColor.getBlue() * (1 - ratio) + endColor.getBlue() * ratio)
|
||||
);
|
||||
}
|
||||
|
||||
// 辅助方法
|
||||
public Point getHead() { return body.getFirst(); }
|
||||
public boolean contains(Point point) { return body.contains(point); }
|
||||
public LinkedList<Point> getBody() { return new LinkedList<>(body); }
|
||||
}
|
Loading…
Reference in new issue