⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpgcanvas.java

📁 游戏源代码 RPG 实现行走 绘制地图 和碰撞交互的功能
💻 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;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -