?? snake.java
字號:
package cn.itcast.snake.entities;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import cn.itcast.snake.listener.SnakeListener;
import cn.itcast.snake.util.Global;
/**
*
* 蛇<BR>
* move()方法默認支持走到邊以后從另一邊出現<BR>
* <BR>
* 可以用setHeadColor(), 和 setBodyColor() 方法更改蛇頭或蛇身體的顏色<BR>
* <BR>
* 也可以通過覆蓋 drawHead(Graphics, int, int, int, int) 方法 改變蛇頭的顯示方式 和覆蓋
* drawBody(Graphics, int, int, int, int) 方法 改變蛇身體的顯示方式<BR>
* <BR>
* 用內部類MoveDriver 驅動蛇定時移動<BR>
* begin() 方法內部開啟一個新的線程驅動蛇定時移動, 調用這個方法的時候要注意<BR>
*
* 蛇的身體的初始長度必須大于等于2
*
* @version 1.0, 01/01/08
*
* @author 湯陽光
*
*/
public class Snake {
/**
* 方向上
*/
public static final int UP = 1;
/**
* 方向下
*/
public static final int DOWN = -1;
/**
* 方向左
*/
public static final int LEFT = 2;
/**
* 方向右
*/
public static final int RIGHT = -2;
/* 蛇(多個節點) */
private LinkedList<Point> body = new LinkedList<Point>();
/* 上一次的移動方向 */
private int oldDirection;
/* 下一步的方向(有效方向) */
private int newDirection;
/* 臨時存放蛇頭的坐標 */
private Point head;
/* 臨時存放蛇尾巴的坐標 */
private Point tail;
/* 移動速度 */
private int speed;
/* 生命, 是否活著 */
private boolean live;
/* 是否暫停 */
private boolean pause;
private Set<SnakeListener> listeners = new HashSet<SnakeListener>();
public static final Color DEFAULT_HEAD_COLOR = new Color(0xcc0033);
/* 蛇頭的顏色 */
private Color headColor = DEFAULT_HEAD_COLOR;
public static final Color DEFAULT_BODY_COLOR = new Color(0xcc0033);
/* 蛇身體的顏色 */
private Color bodyColor = DEFAULT_BODY_COLOR;
/**
* 移動一步, 會忽略相反方向
*/
public void move() {
/* 忽略相反方向 */
if (oldDirection + newDirection != 0)
oldDirection = newDirection;
/* 把蛇尾巴拿出來重新設置坐標作為新蛇頭 */
/* getLocation 將返回一個新的Point */
/* tail把尾巴坐標保存下來, 吃到食物時再加上 */
tail = (head = takeTail()).getLocation();
/* 根據蛇頭的坐標再 上下左右 */
head.setLocation(getHead());
/* 根據方向讓蛇移動 */
switch (oldDirection) {
case UP:
head.y--;
/* 到邊上了可以從另一邊出現 */
if (head.y < 0)
head.y = Global.HEIGHT - 1;
break;
case DOWN:
head.y++;
/* 到邊上了可以從另一邊出現 */
if (head.y == Global.HEIGHT)
head.y = 0;
break;
case LEFT:
head.x--;
/* 到邊上了可以從另一邊出現 */
if (head.x < 0)
head.x = Global.WIDTH - 1;
break;
case RIGHT:
head.x++;
/* 到邊上了可以從另一邊出現 */
if (head.x == Global.WIDTH)
head.x = 0;
break;
}
/* 添加到頭上去 */
body.addFirst(head);
}
/**
* 一個內部類, 驅動蛇定時移動
*
* @author 湯陽光
*
*/
private class SnakeDriver implements Runnable {
public void run() {
// TODO Auto-generated method stub
while (live) {
if (!pause) {
move();
/* 觸發 ControllerListener 的狀態改變事件 */
for (SnakeListener l : listeners)
l.snakeMoved();
}
try {
Thread.sleep(speed);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 在尾巴上增加一個節點
*/
public void eatFood() {
/* 把上一次移動拿掉的節點再加上 */
body.addLast(tail.getLocation());
/* 觸發SnakeListener 的 snakeEatFood 事件 */
for (SnakeListener l : listeners)
l.snakeEatFood();
}
/**
* 改變方向
*
* @param direction
*/
public void changeDirection(int direction) {
this.newDirection = direction;
}
/**
* 得到蛇頭節點
*
* @return
*/
public Point getHead() {
/* 自己約定哪個是蛇頭 */
return body.getFirst();
}
/**
* 拿掉蛇尾巴節點
*
* @return
*/
public Point takeTail() {
/* 去掉蛇尾巴 */
return body.removeLast();
}
/**
* 得到蛇的長度
*
* @return
*/
public int getLength() {
return body.size();
}
/**
* 讓蛇開始運動<BR>
* 開啟一個新的線程
*/
public void begin() {
new Thread(new SnakeDriver()).start();
}
/**
* 讓蛇復活, 并開始運動<BR>
* 將調用 begin() 方法
*/
public void reNew() {
init();
begin();
}
/**
* 初始化蛇的信息<BR>
* 長度, 位置, 方向, 速度, 生命和暫停狀態
*/
public void init() {
body.clear();
/* 初始化位置在中間 */
int x = Global.WIDTH / 2 - Global.INIT_LENGTH / 2;
int y = Global.HEIGHT / 2;
for (int i = 0; i < Global.INIT_LENGTH; i++)
this.body.addFirst(new Point(x++, y));
/* 設置默認方向為向右 */
oldDirection = newDirection = RIGHT;
/* 初始化速度 */
speed = Global.SPEED;
/* 初始化生命和暫停狀態 */
live = true;
pause = false;
}
/**
* 是否吃到自己的身體<BR>
*
* @return 蛇頭的坐標是否和自己的身體的某一個坐標重合
*/
public boolean isEatBody() {
/* 要把蛇頭排除, body.get(0) 是蛇頭 */
for (int i = 1; i < body.size(); i++)
if (getHead().equals(body.get(i)))
return true;
return false;
}
/**
* 畫自己<BR>
* 將調用 drawHead(Graphics, int, int, int, int) 方法 和 drawBody(Graphics, int,
* int, int, int) 方法
*
* @param g
*/
public void drawMe(Graphics g) {
for (Point p : body) {
/* 畫蛇身體 */
g.setColor(bodyColor);
drawBody(g, p.x * Global.CELL_WIDTH, p.y * Global.CELL_HEIGHT,
Global.CELL_WIDTH, Global.CELL_HEIGHT);
}
/* 畫蛇頭 */
g.setColor(headColor);
drawHead(g, getHead().x * Global.CELL_WIDTH, getHead().y
* Global.CELL_HEIGHT, Global.CELL_WIDTH, Global.CELL_HEIGHT);
}
/**
* 畫蛇頭, 可以覆蓋這個方法改變蛇頭的顯示
*
* @param g
* @param x
* 像素坐標 x
* @param y
* 像素坐標 y
* @param width
* 寬度(單位:像素)
* @param height
* 高度(單位:像素)
*/
public void drawHead(Graphics g, int x, int y, int width, int height) {
g.fill3DRect(x, y, width, height, true);
}
/**
* 畫蛇的一節身體, 可以覆蓋這個方法改變蛇的身體節點的顯示
*
* @param g
* @param x
* 像素坐標 x
* @param y
* 像素坐標 y
* @param width
* 寬度(單位:像素)
* @param height
* 高度(單位:像素)
*/
public void drawBody(Graphics g, int x, int y, int width, int height) {
g.fill3DRect(x, y, width, height, true);
}
/**
* 得到蛇頭的顏色
*
* @return
*/
public Color getHeadColor() {
return headColor;
}
/**
* 設置蛇頭的顏色
*
* @param headColor
*/
public void setHeadColor(Color headColor) {
this.headColor = headColor;
}
/**
* 得到蛇身體的顏色
*
* @return
*/
public Color getBodyColor() {
return bodyColor;
}
/**
* 設置蛇身體的顏色
*
* @param bodyColor
*/
public void setBodyColor(Color bodyColor) {
this.bodyColor = bodyColor;
}
/**
* 添加監聽器
*
* @param l
*/
public synchronized void addSnakeListener(SnakeListener l) {
if (l == null)
return;
this.listeners.add(l);
}
/**
* 移除監聽器
*
* @param l
*/
public synchronized void removeSnakeListener(SnakeListener l) {
if (l == null)
return;
this.listeners.remove(l);
}
/**
* 加速, 幅度為 Global 中設置的 SPEED_STEP <BR>
* 在有效的速度范圍之內(增加后速度大于 0毫秒/格)
*/
public void speedUp() {
if (speed > Global.SPEED_STEP)
speed -= Global.SPEED_STEP;
}
/**
* 減速, 幅度為 Global 中設置的 SPEED_STEP
*/
public void speedDown() {
speed += Global.SPEED_STEP;
}
/**
* 得到蛇的移動速度
*
* @return
*/
public int getSpeed() {
return speed;
}
/**
* 設置蛇的移動速度
*
* @param speed
*/
public void setSpeed(int speed) {
this.speed = speed;
}
/**
* 蛇是否死掉了
*
* @return
*/
public boolean isLive() {
return live;
}
/**
* 設置蛇是否死掉
*
* @param live
*/
public void setLive(boolean live) {
this.live = live;
}
/**
* 設置蛇死掉
*/
public void dead() {
this.live = false;
}
/**
* 是否是暫停狀態
*
* @return
*/
public boolean isPause() {
return pause;
}
/**
* 設置暫停狀態
*
* @param pause
*/
public void setPause(boolean pause) {
this.pause = pause;
}
/**
* 更改暫停狀態<BR>
* 若是暫停狀態, 則繼續移動<BR>
* 若正在移動, 則暫停
*/
public void changePause() {
pause = !pause;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -