www.pudn.com > RPGDemo.rar > RPGCanvas.java


import javax.microedition.lcdui.*; 
 
/** 
 * RPG游戏示例代码 实现了按键的连续移动 
 */ 
public class RPGCanvas extends Canvas implements Runnable { 
 
	/** 游戏状态 */ 
	private int status; 
 
	// 游戏状态设定 
	/** 村庄1 */ 
	private final static int SCREEN_1 = 0; 
 
	/** 武器店 */ 
	private final static int WEAPON_SHOP = 10; 
 
	/** 对话状态1 */ 
	private final static int DIALOAG_1 = 100; 
 
	// 场景1地图数组 
	int backmap0[][] = { { 1, 11, 12, 1, 76, 1, 1, 1, 78, 1, 1, 1 }, 
			{ 19, 20, 21, 22, 73, 80, 81, 1, 77, 68, 1, 1 }, 
			{ 28, 29, 30, 31, 32, 1, 1, 1, 1, 1, 1, 1 }, 
			{ 37, 38, 39, 31, 41, 1, 1, 1, 1, 1, 54, 1 }, 
			{ 46, 47, 48, 49, 50, 1, 1, 1, 1, 1, 1, 1 }, 
			{ 55, 74, 57, 58, 59, 1, 1, 1, 1, 1, 1, 1 }, 
			{ 79, 75, 66, 67, 1, 1, 1, 3, 4, 5, 1, 1 }, 
			{ 1, 1, 1, 1, 1, 1, 1, 2, 13, 14, 1, 1 }, 
			{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 
			{ 54, 27, 24, 24, 23, 83, 24, 24, 24, 24, 26, 54 }, 
			{ 15, 43, 9, 9, 23, 83, 9, 9, 9, 9, 25, 15 }, 
			{ 54, 42, 33, 33, 23, 83, 33, 33, 33, 33, 34, 54 }, 
			{ 1, 1, 1, 1, 84, 84, 1, 1, 1, 1, 1, 1 } }; 
 
	// 图块常量 
	/** 每个图块的宽度 */ 
	private final static int TILE_WIDTH = 16; 
	/** 每个图块的高度 */ 
	private final static int TILE_HEIGHT = 16; 
 
	/** 场景1图片 */ 
	Image screen_1 = null; 
 
	/** 地图原始图片 */ 
	Image map0Img = null; 
 
	/** 人物原始图片 */ 
	Image roleImg = null; 
	/** 人物的x坐标 */ 
	int roleX = 100; 
	/** 任务的y坐标 */ 
	int roleY = 100; 
 
	/** 人物宽度 */ 
	private final static int ROLE_WIDTH = 16; 
	/** 人物高度 */ 
	private final static int ROLE_HEIGHT = 32; 
 
	/** 人物方向 */ 
	int direction; 
	/** 人物当前显示图片的序号 */ 
	int currIndex = 0; 
 
	/** 人物连续移动的控制变量,-1代表不移动,其他方向和人物方向常量的规定相同 */ 
 
	int roleMoveControl = -1; 
 
	/** 移动速度,每次2个像素 */ 
	int speed = 4; 
 
	/** 不移动 */ 
	private final static int NOT_MOVE = -1; 
 
	/** 人物方向常量 */ 
	private final static int DIRE_LEFT = 9; 
	private final static int DIRE_RIGHT = 6; 
	private final static int DIRE_UP = 3; 
	private final static int DIRE_DOWN = 0; 
 
	/** 屏幕宽度 */ 
	int width; 
	/** 屏幕高度 */ 
	int height; 
 
	/** 可行走区域地图块序号 */ 
	private int[] canMoveTile = { 1, 2, 3, 4, 5, 13, 14, 23, 32, 41, 50, 59, 
			66, 67, 83 }; 
	 
	/**武器名称*/ 
	private String[] weaponName = { 
		"轩辕剑", 
		"浪宇刀", 
		"匕首" 
	}; 
	 
	/**武器价格*/ 
	private int[] weaponPrice = { 
		1000, 
		2000, 
		100 
	}; 
 
	 
	 
	 
	public RPGCanvas() { 
		try { 
			map0Img = Image.createImage("/map.png"); 
			roleImg = Image.createImage("/player.png"); 
		} catch (Exception e) { 
		} 
		 
		//全屏 
		this.setFullScreenMode(true); 
		 
		width = this.getWidth(); 
		height = this.getHeight(); 
 
		// 启动线程 
		Thread th = new Thread(this); 
		th.start(); 
	} 
 
	protected void paint(Graphics g) { 
		// 根据游戏状态实现绘制 
		switch (status) { 
		case SCREEN_1: 
			// 绘制场景 
			paintSCREEN_1(g); 
			// 绘制人物 
			paintRole(g); 
			break; 
		case WEAPON_SHOP: 
			paintWEAPON_SHOP(g); 
			break; 
		case DIALOAG_1: 
			paintDIALOAG_1(g); 
			break; 
		} 
	} 
 
	/** 
	 * 绘制场景1的方法 
	 *  
	 * @param g 
	 *            画笔 
	 */ 
	private void paintSCREEN_1(Graphics g) { 
		// 构造地图图片 
		if (screen_1 == null) { 
			screen_1 = createScreen_1(); 
		} 
		g.drawImage(screen_1, 0, 0, Graphics.LEFT | Graphics.TOP); 
	} 
 
	/** 
	 * 绘制人物 
	 *  
	 * @param g 
	 *            画笔 
	 */ 
	private void paintRole(Graphics g) { 
		g.setClip(roleX, roleY, ROLE_WIDTH, ROLE_HEIGHT); 
		g.drawImage(roleImg, roleX - currIndex * ROLE_WIDTH, roleY, 
				Graphics.LEFT | Graphics.TOP); 
		// 恢复默认剪切区域 
		g.setClip(0, 0, width, height); 
	} 
 
	String weaponShopName = "武器店"; 
	String left = "离开"; 
	/** 
	 * 绘制武器店界面 
	 *  
	 * @param g 
	 *            画笔 
	 */ 
	private void paintWEAPON_SHOP(Graphics g) { 
		//绘制背景 
		g.setColor(0); 
		g.fillRect(0, 0, width, height); 
		 
		g.setColor(0xffffff); 
		 
		//绘制标题 
		g.drawString(weaponShopName,90,10,Graphics.TOP | Graphics.LEFT); 
		 
		//循环绘制 
		for(int i = 0; i < weaponName.length;i++){ 
			//绘制武器名称 
			g.drawString(weaponName[i], 30,  
					50 + 30 * i, Graphics.TOP | Graphics.LEFT); 
			//绘制武器价格 
			g.drawString("" + weaponPrice[i], 150, 50 + 30 * i, Graphics.TOP | Graphics.LEFT); 
		} 
		 
		//绘制按钮 
		g.drawString(left, 0, height, Graphics.BOTTOM | Graphics.LEFT); 
		 
	} 
 
	/** 
	 * 绘制对话 
	 *  
	 * @param g 
	 *            画笔 
	 */ 
	private void paintDIALOAG_1(Graphics g) { 
 
	} 
 
	private Image createScreen_1() { 
		// 创建和地图大小一样的图片 
		Image tempImg = Image.createImage(backmap0[0].length * TILE_WIDTH, 
				backmap0.length * TILE_HEIGHT); 
		// 绘制地图 
		Graphics g1 = tempImg.getGraphics(); 
		// 循环绘制 
		for (int i = 0; i < backmap0.length; i++) { // 行 
			for (int j = 0; j < backmap0[i].length; j++) { 
				// 设置剪切区域 
				g1.setClip(j * TILE_WIDTH, i * TILE_HEIGHT, TILE_WIDTH, 
						TILE_HEIGHT); 
 
				// 计算图片坐标 
				int dx = (backmap0[i][j] - 1) % 9 * TILE_WIDTH; 
				int dy = (backmap0[i][j] - 1) / 9 * TILE_HEIGHT; 
				// 绘制图片 
				g1.drawImage(map0Img, j * TILE_WIDTH - dx, 
						i * TILE_HEIGHT - dy, Graphics.LEFT | Graphics.TOP); 
			} 
		} 
 
		return tempImg; 
	} 
 
	public void keyPressed(int keyCode) { 
		//System.out.println(keyCode); 
		// 根据游戏状态实现按键处理 
		switch (status) { 
		case SCREEN_1: 
			SCREEN_1_KeyPress(keyCode); 
			break; 
		case WEAPON_SHOP: 
			weapon_Shop_KeyPress(keyCode); 
			break; 
		case DIALOAG_1: 
 
			break; 
		} 
	} 
	 
	/** 
	 * 武器店事件处理 
	 * @param keyCode 
	 */ 
	private void weapon_Shop_KeyPress(int keyCode){ 
		if(keyCode == -6){ //左软键 
			status = SCREEN_1; //切换到村庄 
			//处理坐标 
			roleX = 38; 
			roleY = 100; 
			 
			//人物方向 
			direction = DIRE_DOWN; 
			//人物静止 
			roleMoveControl = NOT_MOVE; 
		} 
	} 
 
	public void keyReleased(int keyCode) { 
		// 根据游戏状态实现按键处理 
		switch (status) { 
		case SCREEN_1: 
			SCREEN_1_KeyRelease(keyCode); 
			break; 
		case WEAPON_SHOP: 
 
			break; 
		case DIALOAG_1: 
 
			break; 
		} 
 
	} 
 
	private void SCREEN_1_KeyPress(int keyCode) { 
		// 转换为游戏动作 
		int action = this.getGameAction(keyCode); 
		switch (action) { 
		case UP: 
			// 改变方向 
			direction = DIRE_UP; 
			// 控制移动 
			roleMoveControl = DIRE_UP; 
			break; 
		case DOWN: 
			// 改变方向 
			direction = DIRE_DOWN; 
			// 控制移动 
			roleMoveControl = DIRE_DOWN; 
			break; 
		case LEFT: 
			// 改变方向 
			direction = DIRE_LEFT; 
			// 控制移动 
			roleMoveControl = DIRE_LEFT; 
			break; 
		case RIGHT: 
			// 改变方向 
			direction = DIRE_RIGHT; 
			// 控制移动 
			roleMoveControl = DIRE_RIGHT; 
			break; 
		case FIRE: 
 
			break; 
		} 
	} 
 
	private void SCREEN_1_KeyRelease(int keyCode) { 
		// 转换为游戏动作 
		int action = this.getGameAction(keyCode); 
		switch (action) { 
		case UP: 
		case DOWN: 
		case LEFT: 
		case RIGHT: 
			roleMoveControl = NOT_MOVE; 
		} 
	} 
 
	Runtime rt = Runtime.getRuntime(); 
	public void run() { 
		try { 
			while (true) { 
				// 延时 
				Thread.sleep(100); 
 
				// 逻辑处理方法 
				tick(); 
				 
				//判断 
				if(rt.freeMemory() < 100000){ 
					System.gc(); 
				} 
 
				// 重新绘制 
				repaint(); 
			} 
		} catch (Exception e) { 
 
		} 
	} 
 
	/** 
	 * 逻辑处理方法 
	 */ 
	public void tick() { 
		// 根据游戏状态实现绘制 
		switch (status) { 
		case SCREEN_1: 
			roleMove(); 
			break; 
		case WEAPON_SHOP: 
 
			break; 
		case DIALOAG_1: 
 
			break; 
		} 
	} 
 
	/** 
	 * 人物移动处理方法 
	 */ 
	private void roleMove() { 
		if (roleMoveControl != NOT_MOVE) { // 人物移动 
			//是否进入武器店 
			if(isDisplayWeaponShop()){ 
				status = WEAPON_SHOP; 
			} 
			// 根据方向移动 
			switch (direction) { 
			case DIRE_LEFT: 
				// 向左移动 
				// 左边界检测 
				if (roleX - speed >= 0) { 
					roleX -= speed; 
					// 如果发生碰撞,则退回 
					if (collis()) { 
						roleX += speed; 
					} 
				} 
				break; 
			case DIRE_RIGHT: 
				// 向右移动 
				// 右边界检测 
				if (roleX + ROLE_WIDTH + speed <= width) { 
					roleX += speed; 
					// 如果发生碰撞,则退回 
					if (collis()) { 
						roleX -= speed; 
					} 
				} 
				break; 
			case DIRE_UP: 
				// 向上移动 
				// 上边界检测 
				if (roleY - speed >= 0) { 
					roleY -= speed; 
					// 如果发生碰撞,则退回 
					if (collis()) { 
						roleY += speed; 
					} 
				} 
				break; 
			case DIRE_DOWN: 
				// 向下移动 
				// 下边界检测 
				if (roleY + ROLE_HEIGHT + speed <= height) { 
					roleY += speed; 
					// 如果发生碰撞,则退回 
					if (collis()) { 
						roleY -= speed; 
					} 
				} 
				break; 
			} 
			// 动画 
			if (currIndex == direction + 1) { 
				currIndex = direction + 2; 
			} else { 
				currIndex = direction + 1; 
			} 
		} else { // 人物静止 
			currIndex = direction; 
		} 
	} 
 
	/** 
	 * 碰撞检测  
	 * 原理:以人物16X32区域的下半部12X12和地图坐标判断, 
	 * 只有地图块 为可移动地图块数组的才能够行走 
	 *  
	 * @return true代表发生碰撞,false代表未碰撞 
	 */ 
	private boolean collis() { 
		// 获得12X12区域的坐标,左上角 
		int leftX = roleX + 2; 
		int topY = roleY + 18; 
 
		// 计算左上角所在的地图图块的序号 
		int col = leftX / TILE_WIDTH; 
		int row = topY / TILE_HEIGHT; 
		if (!canMove(row, col)) { 
			return true; 
		} 
		// 右上角所在的地图图块的序号 
		col = (leftX + 12) / TILE_WIDTH; 
		if (!canMove(row, col)) { 
			return true; 
		} 
		// 左下角所在的地图图块的序号 
		col = leftX / TILE_WIDTH; 
		row = (topY + 12) / TILE_WIDTH; 
		if (!canMove(row, col)) { 
			return true; 
		} 
		// 右下角 
		col = (leftX + 12) / TILE_WIDTH; 
		if (!canMove(row, col)) { 
			return true; 
		} 
 
		// 如果都不满足,则返回false 
		return false; 
	} 
 
	/** 
	 * 第row行第col列图块是否可行走 
	 *  
	 * @param row 
	 *            行号,从0开始 
	 * @param col 
	 *            列号,从0开始 
	 * @return true代表可以行走,false代表不能行走 
	 */ 
	private boolean canMove(int row, int col) { 
		boolean b = false; 
		for (int i = 0; i < canMoveTile.length; i++) { 
			if (backmap0[row][col] == canMoveTile[i]) { 
				b = true; 
				break; 
			} 
		} 
		return b; 
	} 
	 
	/** 
	 * 是否进入武器店 
	 * @return true代表进入 
	 */ 
	private boolean isDisplayWeaponShop(){ 
		// 获得16X16区域的坐标,左上角 
		int leftX = roleX; 
		int topY = roleY + 16; 
 
		// 计算左上角所在的地图图块的序号 
		int col = leftX / TILE_WIDTH; 
		int row = topY / TILE_HEIGHT; 
		//是否和门发生碰撞 
		if(backmap0[row][col] == 66){ //门 
			//status = WEAPON_SHOP; 
			return true; 
		}		 
		// 右上角所在的地图图块的序号 
		col = (leftX + 12) / TILE_WIDTH; 
		//是否和门发生碰撞 
		if(backmap0[row][col] == 66){ //门 
			//status = WEAPON_SHOP; 
			return true; 
		} 
		 
		return false; 
	} 
}