import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.List;
public class Snake {
private static final int MOVE_LEFT = 0;
private static final int MOVE_UP = 1;
private static final int MOVE_RIGHT = 2;
private static final int MOVE_DOWN = 3;
private static final int CURVE_RIGHT_UP = 0;
private static final int CURVE_RIGHT_DOWN = 1;
private static final int CURVE_LEFT_DOWN = 2;
private static final int CURVE_LEFT_UP = 3;
private static final int KEY_LEFT = 37;
private static final int KEY_UP = 38;
private static final int KEY_RIGHT = 39;
private static final int KEY_DOWN = 40;
public static int SNAKE_WIDTH = 10;
public static int SNAKE_HEIGHT = 10;
private int direction;
private int posX;
private int posY;
private List positions;
private Statistik statistik;
public Snake(Statistik statistik) {
this.statistik = statistik;
direction = MOVE_RIGHT;
posX = Game.FRAME_WIDTH / 2;
posY = Game.FRAME_HEIGHT / 2;
positions = new ArrayList();
addPoint(new int[] { posX, posY }, false);
addPoint(new int[] { posX, posY }, false);
addPoint(new int[] { posX, posY }, false);
addPoint(new int[] { posX, posY }, false);
addPoint(new int[] { posX, posY }, false);
addPoint(new int[] { posX, posY }, false);
}
public void keyResolver(int newDirection) {
switch (newDirection) {
case KEY_LEFT:
// case left
if (this.direction != MOVE_RIGHT) {
this.direction = MOVE_LEFT;
}
break;
case KEY_UP:
// case up
if (this.direction != MOVE_DOWN) {
this.direction = MOVE_UP;
}
break;
case KEY_RIGHT:
// case right
if (this.direction != MOVE_LEFT) {
this.direction = MOVE_RIGHT;
}
break;
case KEY_DOWN:
// case down
if (this.direction != MOVE_UP) {
this.direction = MOVE_DOWN;
}
break;
}
}
public void move(boolean add) {
if (direction == MOVE_LEFT) {
posX -= SNAKE_WIDTH;
} else if (direction == MOVE_UP) {
posY -= SNAKE_HEIGHT;
} else if (direction == MOVE_RIGHT) {
posX += SNAKE_WIDTH;
} else if (direction == MOVE_DOWN) {
posY += SNAKE_HEIGHT;
}
jump();
if (!add && positions.size() != 0) {
positions.remove(0);
}
positions.add(new int[] { posX, posY, direction });
}
private void jump() {
if (posX < 0) {
// left out
posX = Game.FRAME_WIDTH - SNAKE_WIDTH;
} else if (posX >= Game.FRAME_WIDTH) {
// right out
posX = 0;
} else if (posY < 0) {
// top out
posY = Game.FRAME_HEIGHT - SNAKE_HEIGHT;
} else if (posY >= Game.FRAME_HEIGHT) {
// bottom out
posY = 0;
}
}
public boolean isCollision() {
int[][] positionHelper = (int[][])positions.toArray(new int[][] {});
for (int i = 0; i < positions.size(); i++) {
for (int j = i + 1; j < positions.size(); j++) {
if (isCollision(positionHelper[i], positionHelper[j])) {
return true;
}
}
}
return false;
}
public boolean isCollision(int[] point) {
int[][] positionHelper = (int[][])positions.toArray(new int[][] {});
for (int i = 0; i < positions.size(); i++) {
if (isCollision(positionHelper[i], point)) {
return true;
}
}
return false;
}
private boolean isCollision(int[] point1, int[] point2) {
return point1[0] != -1 && point1[0] == point2[0] && point1[1] != -1
&& point1[1] == point2[1];
}
public void draw(Graphics2D g2, Insets insets) {
int[] tmp;
for (int i = 1; i < positions.size() - 1; i++) {
tmp = (int[])positions.get(i);
if (!isCurve(i)) {
g2.fillRect(tmp[0] + insets.left, tmp[1] + insets.top,
SNAKE_WIDTH, SNAKE_HEIGHT);
} else {
drawCurve(i, g2, insets);
}
}
drawFirst(g2, insets);
drawLast(g2, insets);
}
private void drawCurve(int i, Graphics2D g2, Insets insets) {
int[] tmp = (int[])positions.get(i);
g2.fillOval(tmp[0] + insets.left, tmp[1] + insets.top, SNAKE_WIDTH,
SNAKE_HEIGHT);
int curve = curveType(i);
if (curve == CURVE_RIGHT_UP) {
g2.fillRect(tmp[0] + insets.left, tmp[1] + insets.top
+ SNAKE_HEIGHT / 2, SNAKE_WIDTH, SNAKE_HEIGHT / 2);
g2.fillRect(tmp[0] + insets.left, tmp[1] + insets.top,
SNAKE_WIDTH / 2, SNAKE_HEIGHT / 2);
} else if (curve == CURVE_RIGHT_DOWN) {
g2.fillRect(tmp[0] + insets.left, tmp[1] + insets.top, SNAKE_WIDTH,
SNAKE_HEIGHT / 2);
g2.fillRect(tmp[0] + insets.left, tmp[1] + insets.top
+ SNAKE_HEIGHT / 2, SNAKE_WIDTH / 2, SNAKE_HEIGHT / 2);
} else if (curve == CURVE_LEFT_DOWN) {
g2.fillRect(tmp[0] + insets.left, tmp[1] + insets.top, SNAKE_WIDTH,
SNAKE_HEIGHT / 2);
g2.fillRect(tmp[0] + insets.left + SNAKE_WIDTH / 2 + 1, tmp[1]
+ insets.top + SNAKE_WIDTH / 2, SNAKE_WIDTH / 2,
SNAKE_HEIGHT / 2);
} else if (curve == CURVE_LEFT_UP) {
g2.fillRect(tmp[0] + insets.left, tmp[1] + insets.top
+ SNAKE_HEIGHT / 2, SNAKE_WIDTH, SNAKE_HEIGHT / 2);
g2.fillRect(tmp[0] + insets.left + SNAKE_WIDTH / 2 + 1, tmp[1]
+ insets.top, SNAKE_WIDTH / 2, SNAKE_HEIGHT / 2);
}
}
private int curveType(int i) {
int[] cur = (int[])positions.get(i);
int[] post = (int[])positions.get(i + 1);
if (cur[2] == post[2]) {
return -1;
} else if ((cur[2] == MOVE_RIGHT && post[2] == MOVE_UP)
|| (cur[2] == MOVE_DOWN && post[2] == MOVE_LEFT)) {
return CURVE_RIGHT_DOWN;
} else if ((cur[2] == MOVE_RIGHT && post[2] == MOVE_DOWN)
|| (cur[2] == MOVE_UP && post[2] == MOVE_LEFT)) {
return CURVE_RIGHT_UP;
} else if ((cur[2] == MOVE_LEFT && post[2] == MOVE_UP)
|| (cur[2] == MOVE_DOWN && post[2] == MOVE_RIGHT)) {
return CURVE_LEFT_DOWN;
} else if ((cur[2] == MOVE_LEFT && post[2] == MOVE_DOWN)
|| (cur[2] == MOVE_UP && post[2] == MOVE_RIGHT)) {
return CURVE_LEFT_UP;
}
return -1;
}
private boolean isCurve(int i) {
return curveType(i) != -1;
}
private void drawFirst(Graphics2D g2, Insets insets) {
int[] first = (int[])positions.get(positions.size() - 1);
g2.fillOval(first[0] + insets.left, first[1] + insets.top, SNAKE_WIDTH,
SNAKE_HEIGHT);
if (first[2] == MOVE_UP) {
g2.fillRect(first[0] + insets.left, first[1] + insets.top
+ SNAKE_HEIGHT / 2 + 1, SNAKE_WIDTH, SNAKE_HEIGHT / 2);
} else if (first[2] == MOVE_DOWN) {
g2.fillRect(first[0] + insets.left, first[1] + insets.top,
SNAKE_WIDTH, SNAKE_HEIGHT / 2);
} else if (first[2] == MOVE_LEFT) {
g2.fillRect(first[0] + insets.left + SNAKE_WIDTH / 2 + 1, first[1]
+ insets.top, SNAKE_WIDTH / 2, SNAKE_HEIGHT);
} else if (first[2] == MOVE_RIGHT) {
g2.fillRect(first[0] + insets.left, first[1] + insets.top,
SNAKE_WIDTH / 2, SNAKE_HEIGHT);
}
}
private void drawLast(Graphics2D g2, Insets insets) {
int[] last = (int[])positions.get(0);
int[] pre = (int[])positions.get(1);
Color c = g2.getColor();
if (pre[2] == MOVE_UP) {
for (int i = 0; i < SNAKE_HEIGHT; i++) {
g2.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), c
.getAlpha()
/ (i + 1)));
g2.fillRect(last[0] + insets.left, last[1] + insets.top + i,
SNAKE_WIDTH, 1);
}
} else if (pre[2] == MOVE_DOWN) {
for (int i = 0; i < SNAKE_HEIGHT; i++) {
g2.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), c
.getAlpha()
/ (SNAKE_HEIGHT - i)));
g2.fillRect(last[0] + insets.left, last[1] + insets.top + i,
SNAKE_WIDTH, 1);
}
} else if (pre[2] == MOVE_LEFT) {
for (int i = 0; i < SNAKE_HEIGHT; i++) {
g2.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), c
.getAlpha()
/ (i + 1)));
g2.fillRect(last[0] + insets.left + i, last[1] + insets.top, 1,
SNAKE_WIDTH);
}
} else if (pre[2] == MOVE_RIGHT) {
for (int i = 0; i < SNAKE_HEIGHT; i++) {
g2.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), c
.getAlpha()
/ (SNAKE_HEIGHT - i)));
g2.fillRect(last[0] + insets.left + i, last[1] + insets.top, 1,
SNAKE_WIDTH);
}
}
g2.setColor(Color.BLACK);
}
public boolean addPoint(int[] point, boolean extra) {
if (!isCollision(point, new int[] { posX, posY })) {
return false;
}
if (!extra) {
move(true);
statistik.addStone();
} else {
statistik.addExtraStone();
}
return true;
}
public boolean isAllowedDirection(int keyCode) {
if (keyCode == KEY_RIGHT || keyCode == KEY_LEFT) {
return !(this.direction == MOVE_RIGHT || this.direction == MOVE_LEFT);
}
if (keyCode == KEY_UP || keyCode == KEY_DOWN) {
return !(this.direction == MOVE_DOWN || this.direction == MOVE_UP);
}
return false;
}
}