<span style="font-size:18px;">package com.lovo; /** * 方向(枚舉類) * @author hechao * */ public enum Direction { UP, DOWN, LEFT, RIGHT }</span>
<span style="font-size:18px;">package com.lovo; import java.awt.Color; import java.awt.Graphics; public class Egg { private int x, y; private int size = GameContext.EGG_SIZE; public Egg() { int minX = GameContext.WALL_X / 20; int maxX = (GameContext.SQUARE_SIZE - GameContext.EGG_SIZE) / 20; x = (int) (Math.random() * maxX + minX) * 20; int minY = GameContext.WALL_Y / 20; int maxY = maxX; y = (int) (Math.random() * maxY + minY) * 20; } public int getX() { return x; } public int getY() { return y; } public void draw(Graphics g) { g.setColor(Color.ORANGE); g.fillOval(x, y, size, size); } } </span>
<span style="font-size:18px;">package com.lovo; public class GameContext { /** * 蛇的長度 */ public static final int SNAKE_LENGTH = 1; /** * 蛇頭初始位置的橫座標 */ public static final int SNAKE_X = 260; /** * 蛇頭初始位置的縱座標 */ public static final int SNAKE_Y = 280; /** * 蛇節點的大小 */ public static final int SNAKE_SIZE = 20; /** * 遊戲窗口的大小 */ public static final int GAME_SIZE = 580; /** * 遊戲場地的大小 */ public static final int SQUARE_SIZE = 500; /** * 刷新週期 */ public static final int INTERVAL = 200; /** * 圍牆起點的橫座標 */ public static final int WALL_X = 40; /** * 圍牆起點的縱座標 */ public static final int WALL_Y = 40; /** * 圍牆厚度 */ public static final int WALL_WIDTH = 5; /** * 蛋的大小 */ public static final int EGG_SIZE = SNAKE_SIZE; } </span>
<pre name="code" class="java">package com.lovo; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Stroke; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.util.LinkedList; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.Timer; @SuppressWarnings("serial") public class GameFrame extends JFrame { private Image offImage = new BufferedImage(GameContext.GAME_SIZE, GameContext.GAME_SIZE, 1); private Timer timer = null; private int score; private Snake snake = new Snake(); // 創建蛇的對象 private Egg egg = new Egg(); // 創建蛋的對象 private JLabel scoreLable; private LinkedList<SnakeNode> list = snake.getList(); public GameFrame() { this.setTitle("貪喫蛇"); this.setSize(GameContext.GAME_SIZE, GameContext.GAME_SIZE); this.setResizable(false); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setLayout(null); this.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { Direction newDir = snake.getDir(); switch(e.getKeyCode()) { case KeyEvent.VK_W: //上 newDir = Direction.UP; break; case KeyEvent.VK_S: // 下 newDir = Direction.DOWN; break; case KeyEvent.VK_A: // 左 newDir = Direction.LEFT; break; case KeyEvent.VK_D: // 右 newDir = Direction.RIGHT; break; case KeyEvent.VK_F2: resetGame(); break; } if(snake.getDir() != newDir) { // 如果新方向不同於蛇原來的方向 snake.changeDir(newDir); // 調用蛇的changeDir方法修改蛇的方向 } } /** * 重置遊戲 */ public void resetGame(){ score = 0; list.clear(); snake.resetSnake(); timer.start(); egg = new Egg(); repaint(); } }); timer = new Timer(GameContext.INTERVAL, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { snake.move(); // 調用蛇的move方法讓蛇移動 if(snake.eatEgg(egg)) { // 喫到蛋 snake.grow(); // 調用蛇的grow方法讓蛇變長 score++; egg = new Egg(); // 重新創建一顆蛋 } SnakeNode head = snake.getHead(); int x = head.getX(); int y = head.getY(); for(int i = 1; i < list.size(); i++){ SnakeNode sn = list.get(i); if(sn.getX() == x && sn.getY() == y){ timer.stop(); } } if(x < GameContext.WALL_X || x > GameContext.WALL_X + GameContext.SQUARE_SIZE - GameContext.SNAKE_SIZE || y < GameContext.WALL_Y || y > GameContext.WALL_Y + GameContext.SQUARE_SIZE - GameContext.SNAKE_SIZE) { timer.stop(); } else { repaint(); } } }); scoreLable = new JLabel(); scoreLable.setBounds(50, 530, 100, 15); GameFrame.this.add(scoreLable); timer.start(); } @Override public void paint(Graphics g) { // 使用雙緩衝方式消除窗口閃爍(見下面步驟1-2-3) // 1. 獲得內存中圖像的畫筆 Graphics offG = offImage.getGraphics(); // 2. 用offG在內存中繪製窗口上的所有內容 super.paint(offG); // 消除殘影 Graphics2D g2d = (Graphics2D) offG; // 將Graphics轉成其子類型Graphics2D並設置粗細 Stroke oldStroke = g2d.getStroke(); // 記錄畫筆粗細(保存現場) g2d.setStroke(new BasicStroke(GameContext.WALL_WIDTH)); // 將畫筆加粗 offG.setColor(Color.BLACK); // 設置畫筆爲黑色 int x = GameContext.WALL_X, y = GameContext.WALL_Y; offG.drawRect(x, y, GameContext.SQUARE_SIZE, GameContext.SQUARE_SIZE); // 繪製圍牆 g2d.setStroke(oldStroke); // 還原畫筆粗細(恢復現場) snake.draw(offG); // 調用蛇的draw方法繪製蛇 egg.draw(offG); // 調用蛋的draw方法繪製蛋 // 3. 將內存中繪製好的圖直接畫到窗口上(雙緩衝) g.drawImage(offImage, 0, 0, null); // 第二個和第三個參數是繪圖的位置 scoreLable.setText("得分:" + score); } }
<span style="font-size:18px;">package com.lovo; class GameRunner { public static void main(String[] args) { new GameFrame().setVisible(true); } } </span>
<pre name="code" class="java">package com.lovo; import java.awt.Graphics; import java.util.LinkedList; /** * 蛇 * @author 何超 * */ public class Snake { private Direction dir = Direction.LEFT; // 方向 private LinkedList<SnakeNode> list = new LinkedList<SnakeNode>(); // 裝蛇的所有節點的容器(鏈表) /** * 構造器 */ public Snake() { // 初始化5個節點 for (int i = 0; i < GameContext.SNAKE_LENGTH; i++) { list.add(new SnakeNode(GameContext.SNAKE_X + i * GameContext.SNAKE_SIZE, GameContext.SNAKE_Y)); } } /** * 獲得蛇結點容器 * @return 蛇結點容器 */ public LinkedList<SnakeNode> getList(){ return list; } /** * 改變方向 * @param newDir 新的方向 */ public void changeDir(Direction newDir) { if(!((dir == Direction.LEFT && newDir == Direction.RIGHT) || (dir == Direction.RIGHT && newDir == Direction.LEFT) || (dir == Direction.UP && newDir == Direction.DOWN) || (dir == Direction.DOWN && newDir == Direction.UP))) { dir = newDir; } } /** * 獲得蛇前進的方向 */ public Direction getDir() { return dir; } /** * 獲得蛇頭 */ public SnakeNode getHead() { return list.get(0); // 容器中的第一個節點就是蛇頭 } /** * 移動 */ public void move() { grow(); list.removeLast(); // 尾巴刪一個節點 } /** * 喫蛋 * @param egg 蛋 * @return 喫到蛋返回true否則返回false */ public boolean eatEgg(Egg egg) { SnakeNode head = getHead(); return head.getX() == egg.getX() && head.getY() == egg.getY(); } /** * 長長一節 */ public void grow() { SnakeNode head = getHead(); int x = head.getX(), y = head.getY(); int size = GameContext.SNAKE_SIZE; switch(dir) { case UP: y -= size; break; case DOWN: y += size; break; case LEFT: x -= size; break; case RIGHT: x += size; break; } SnakeNode newHead = new SnakeNode(x, y); // 創建新的蛇頭節點 list.addFirst(newHead); // 頭上加一個節點 } /** * 重置 */ public void resetSnake() { // 初始化5個節點 for (int i = 0; i < GameContext.SNAKE_LENGTH; i++) { list.add(new SnakeNode(GameContext.SNAKE_X + i * GameContext.SNAKE_SIZE, GameContext.SNAKE_Y)); } } /** * 繪製蛇 */ public void draw(Graphics g) { // 繪製蛇身上的每個節點 for(SnakeNode node : list) { node.draw(g); } } }
<span style="font-size:18px;">package com.lovo; import java.awt.Color; import java.awt.Graphics; /** * 蛇身上的節點 * @author 駱昊 * */ public class SnakeNode { private int x, y; private int size = GameContext.SNAKE_SIZE; /** * 構造器 */ public SnakeNode(int x, int y) { this.x = x; this.y = y; } /** * 蛇節點的橫座標 */ public int getX() { return x; } /** * 蛇節點的縱座標 */ public int getY() { return y; } /** * 繪製 */ public void draw(Graphics g) { g.setColor(Color.GREEN); g.fillRect(x, y, size, size); g.setColor(Color.BLACK); g.drawRect(x, y, size, size); } } </span>
2014.11.17貪喫蛇------老師的修改而來
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.