`
suky
  • 浏览: 145531 次
  • 性别: Icon_minigender_2
  • 来自: 厦门
社区版块
存档分类
最新评论

贪吃蛇游戏的实现

    博客分类:
  • J2ME
阅读更多

    最近刚学J2ME,今天写了个贪吃蛇的游戏,下面提供游戏机制及源代码。

   【游戏机制】:玩家控制由多个矩形组成的蛇,通过按键控制蛇的移动。指定按键功能:
                  2 up
                  4 left
                  6 right
                  8 down
      随机显示食物的位置,当蛇头碰到食物时,将身体节点加1,食物消失。用户不做按键,蛇自动按照当前方向向前移动。
   【游戏算法】:
1、将窗口按照16*16划分成多个网格
2、实现一个蛇头的按键控制
3、通过线程让蛇头自动移动
4、在窗口中随机出现可吃的食物小块 16的倍数
5、实现方块和可以吃的食物小块的碰撞检测
6、将蛇的身体各块定义为Vector,每个块是一个对象
      Node{
           int x,
           int y,
           int nextDir;//下一步要移动的方向
      }
7、判定死亡

   【游戏源代码】:

import java.util.Random;
import java.util.Vector;
import javax.microedition.lcdui.*;

public class SnakeCanvas extends Canvas {

	// 方向标识
	private static final int SNAKE_UP = 1;

	private static final int SNAKE_DOWN = 2;

	private static final int SNAKE_LEFT = 3;

	private static final int SNAKE_RIGHT = 4;

	private static final int SNAKE_STOP = -1;

	private static final int SNAKE_OVER = -2;

	private class Node {
		int x;

		int y;

		int nextDir;
	}

	private Node head;

	private Node eat;

	private Random r1;// 随机对象

	private int screenW;

	private int screenH;

	private Vector allBody;// 蛇身体

	public SnakeCanvas() {

		r1 = new Random();
		screenW = this.getWidth();
		screenH = this.getHeight();

		head = new Node();
		head.x = r1.nextInt(screenW / 2);// 产生一个0-screenW/2的随机数
		head.y = r1.nextInt(screenH / 2);
		head.x = head.x / 16 * 16;// 确保16的倍数
		head.y = head.y / 16 * 16;
		head.nextDir = SNAKE_STOP;// 停止

		allBody = new Vector();

		eat = new Node();
		eat.x = r1.nextInt(screenW / 2);
		eat.y = r1.nextInt(screenH / 2);
		eat.x = eat.x / 16 * 16;
		eat.y = eat.y / 16 * 16;

		startGrame();// 开始游戏
	}

	/** 移动头部* */
	public void moveHead() {

		switch (head.nextDir) {
		case SnakeCanvas.SNAKE_UP:
			head.y -= 16;
			break;
		case SnakeCanvas.SNAKE_LEFT:
			head.x -= 16;
			break;
		case SnakeCanvas.SNAKE_RIGHT:
			head.x += 16;
			break;
		case SnakeCanvas.SNAKE_DOWN:
			head.y += 16;
			break;
		}
	}

	/** 检测碰撞* */
	public void checkEat() {
		if (head.x == eat.x && head.y == eat.y) {// 吃上
			// 1. 添加到蛇身体的向量中
			Node no = new Node();
			Node addNode = null;// 准备插入位置

			if (allBody.size() == 0) {// 插到头部
				addNode = head;
			} else {
				addNode = (Node) allBody.elementAt(allBody.size() - 1);// 插到最后一个节点
			}

			no.nextDir = addNode.nextDir;
			switch (addNode.nextDir) {
			case SnakeCanvas.SNAKE_UP:
				no.x = addNode.x;
				no.y = addNode.y + 16;
				break;
			case SnakeCanvas.SNAKE_LEFT:
				no.x = addNode.x + 16;
				no.y = addNode.y;
				break;
			case SnakeCanvas.SNAKE_RIGHT:
				no.x = addNode.x - 16;
				no.y = addNode.y;
				break;
			case SnakeCanvas.SNAKE_DOWN:
				no.x = addNode.x;
				no.y = addNode.y - 16;
				break;
			}

			this.allBody.addElement(no);

			// 2. 可以吃的小块随机产生
			eat.x = r1.nextInt(screenW / 2);
			eat.y = r1.nextInt(screenH / 2);
			eat.x = eat.x / 16 * 16;
			eat.y = eat.y / 16 * 16;

		} else if (head.x < 0 || head.x > this.screenW || head.y < 0
				|| head.y > this.screenH) {// 死亡检测:碰到墙
			head.nextDir = SnakeCanvas.SNAKE_OVER;
		} else if (allBody.size() > 0) {// 死亡检测:是否有尾巴
			for (int i = 0; i < allBody.size(); i++) {
				Node point = (Node) allBody.elementAt(i);
				if (head.x == point.x && head.y == point.y) {// 碰到尾巴
					head.nextDir = SnakeCanvas.SNAKE_OVER;
				}
			}

		}

	}

	/** 移动所有蛇的身体* */
	public void moveAllNode() {
		int dir = head.nextDir;// 记录上一节点的方向,初始为:当前蛇头方向
		int tmp = 0;
		for (int i = 0; i < allBody.size(); i++) {
			Node now = (Node) allBody.elementAt(i);
			switch (now.nextDir) {
			case SnakeCanvas.SNAKE_UP:
				now.y -= 16;
				break;
			case SnakeCanvas.SNAKE_LEFT:
				now.x -= 16;
				break;
			case SnakeCanvas.SNAKE_RIGHT:
				now.x += 16;
				break;
			case SnakeCanvas.SNAKE_DOWN:
				now.y += 16;
				break;
			}
			tmp = now.nextDir;
			now.nextDir = dir;
			dir = tmp;
		}

	}

	/** 实现游戏中的蛇头的自动移动* */
	public void startGrame() {
		// 规划线程要执行的任务
		Thread t = new Thread() {
			public void run() {
				while (true) {
					// 1. 移动蛇头
					moveHead();
					// 2. 移动所有蛇的身体
					moveAllNode();
					// 3. 碰撞检测
					checkEat();
					// 4. 重新绘制屏幕
					repaint();
					// 5. 休息
					try {
						Thread.sleep(800);
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				}

			}
		};
		if (SnakeCanvas.SNAKE_OVER == head.nextDir) {// 死亡
			t.interrupt();
		} else {
			t.start();
		}

	}

	protected void paint(Graphics g) {
		// 画背景
		g.setColor(255, 255, 255);
		g.fillRect(0, 0, screenW, screenH);
		// 画蛇头
		g.setColor(0, 0, 0);
		g.fillRect(head.x, head.y, 16, 16);
		// 画身体
		g.setColor(0, 255, 0);
		for (int i = 0; i < allBody.size(); i++) {
			Node now = (Node) allBody.elementAt(i);// 获取第i个节点
			g.fillRect(now.x, now.y, 16, 16);
		}
		// 画可以吃的小块
		g.setColor(255, 0, 0);
		g.fillRect(eat.x, eat.y, 16, 16);

		if (SnakeCanvas.SNAKE_OVER == head.nextDir) {// 死亡
			Font overFont = g.getFont();
			int fontH = overFont.getHeight();
			int fontW = overFont.stringWidth("Game Over!");
			g.drawString("Game Over!", (screenW - fontW) / 2,
					(screenH - fontH) / 2, g.TOP | g.LEFT);

		}

	}

	// 相应按键功能( 移动交给线程完成,所以按键只需要控制 下一步移动的方向,就可以了)
	public void keyPressed(int n) {

		switch (n) {
		case Canvas.KEY_NUM2:
			head.nextDir = SnakeCanvas.SNAKE_UP;
			break;
		case Canvas.KEY_NUM4:
			head.nextDir = SnakeCanvas.SNAKE_LEFT;
			break;
		case Canvas.KEY_NUM1:
			head.nextDir = SnakeCanvas.SNAKE_LEFT;
			break;
		case Canvas.KEY_NUM6:
			head.nextDir = SnakeCanvas.SNAKE_RIGHT;
			break;
		case Canvas.KEY_NUM8:
			head.nextDir = SnakeCanvas.SNAKE_DOWN;
			break;

		}
		this.repaint();
	}

	public void keyReleased(int n) {
	}

	public void keyRepeated(int n) {
	}

}

//创建游戏入口类

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class AppMain extends MIDlet {

	protected void startApp() throws MIDletStateChangeException {
		SnakeCanvas mc = new SnakeCanvas();
		Display.getDisplay(this).setCurrent(mc);

	}

	protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
		// TODO 自动生成方法存根

	}

	protected void pauseApp() {
		// TODO 自动生成方法存根

	}

}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics