rpgcanvas.java

来自「一个J2ME的RPG游戏」· Java 代码 · 共 1,841 行 · 第 1/4 页

JAVA
1,841
字号
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Random;
import java.util.Vector;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.media.MediaException;

public class RPGCanvas extends GameCanvas implements Runnable, CommandListener {

	private int screenwidth = getWidth();  //屏幕宽
	private int screenheight = getHeight(); //屏幕高
	private int imgbackgroundwidth = 512;   //地图背景宽
	private int imgbackgroundheight = 512;   //地图背景高

	Thread t;        //游戏线程
	Random r;       //随机数
	RPGMidlet midlet;

	Vector vectormessage;     //保存会话内容
	Vector vectorpicture;    //保存图画
	LayerManager lmscene1, lmscene2;   //场景一,二管理对象
	String missionmessage, curmessage;   //任务消息和当前人物会话内容
	Mainrole mrole;       //游戏主角色
	Load load;      //加载游戏画面
	Graphics g;
	Image curpicture;

	private boolean catchcat = false;    //判断与猫的接触
	private boolean catchcat2 = false;
	private boolean showyesorno = false;   //是否显示会话内容
	private boolean mainroleanswer = false;   //人物回答
	private boolean iscollide = false;    //是否与老人接触了

	private int scene = 1; // check for scene  //场景
	private int inputmode = 0;      //输入模式
	int screenx, screeny, lastscreenx, lastscreeny;  //屏幕当前坐标 和上次移动的坐标大小
	int tempx = 0, tempy = 0;
	int selecty = 152;   //当进行模式选择时,选择光标的位置
	int key;         //获得键盘状态
	
	static int mroleProperty[];  //人物属性数组
	private int roleBloodHeight = 40;  //人物血气的长度

	private boolean ismessage = false;  //npc人物是否显示对话
	private boolean firstTouch = true;  //完成寻找猫后,第一次与老人接触后为false
	private boolean isbeat = false; //判断是否与野怪接触	

	public static final int GAME_MENU = 0;  //游戏菜单状态
	public static final int GAME_START = 1;  //游戏进行状态
	public static final int GAME_PAUSE = 2;   //游戏停止状态
	public static final int GAME_ABOUT = 8;   //游戏介绍状态
	private static final int MENU_START = 3;  //菜单:进入游戏
	private static final int MENU_LOAD = 4; //菜单:载入进度
	private static final int MENU_VOL = 5;   //菜单:声音播放
	private static final int MENU_QUIT = 6;// 菜单: 退出
	private static final int MENU_ABOUT = 7; //菜单:关于游戏
	private static final int MENU_SAVE = 8;// 菜单:保存游戏

	//	public static int DEFAULT_FPS = 10;
	//
	//	private int interval = 1000 / DEFAULT_FPS;

	public Command exitGame = new Command("退出", Command.EXIT, 1);
	public Command mainMenu = new Command("菜单", Command.OK, 1);
	public Command backMenu = new Command("返回菜单", Command.BACK, 2);
	public Command backGame = new Command("返回游戏", Command.BACK, 2);

	private Font font = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD,
			Font.SIZE_SMALL);	
	private int fHeight = font.getHeight();
	
	private int gameAboutY = 0;

	public SaveStateRecord record = null;
	public AudioPlayer bgPlayer;

	// public AudioPlayer beatPlayer;

	public boolean isVolOn = false;
	private boolean isFirstStart;   //判断是否刚启动游戏,尚未进入游戏状态
	private boolean gameOver = false;    //游戏结束标志
	private boolean isBoss = false;    //是否与boss接触
	private boolean isSoldier = false;  //是否与野怪接触
	private boolean isAttack = false;  // 是否攻击选择
	private int number;  //判断接触的是第几个野怪2,3,4分表表示第一,二,三个野怪
	private String soldierWord; //存放野怪或boss对话内容
	private int blood;   //存放野怪或boss所出招数引起的血气减少量
	private int attackWidth;    //每帧招数图片的宽
	private int attackHeight;  //每帧招数图片的高
	private String roleWord = "";  //人物对话内容
	private boolean roleAttack = false;  // 人物招数选择
	private int attackSelecty = screenwidth - 35;   //有三项选择时,游戏光标位置
	private int tempNum;   //随机数
	private boolean roleBeat = false;   //人物放招画面
	private boolean isBossDead = false;   //判断boss死亡
	private boolean isFood = false;   //判断与食物接触
	private boolean isSword = false;  //判断与宝剑接触
	private boolean isChoose = false;  //判断是否攻击boss
	private boolean isBossAttack = false;  //boss攻击
	private int bossBlood = 30;  //boss血气
	private boolean warEnd = false;  //判断与boss战斗是否结束
	private int randX, randY;   //随机获得坐标,用来随机产生道具
	private int gameState;  //游戏状态
	private int menuState;  //菜单状态
	private String choose1, choose2, choose3;  //选择项
	private boolean isGold = false;  //是否与黄金碰撞
	private boolean isSeller = false; //是否与商人碰撞
	private boolean isBuy = false;   //是否买
	private boolean isSell = false; //是否卖
	private boolean forBuy = false;  //选择买
	private boolean forSell = false; //选择卖
	private boolean sellerAsk = false;  //商人询问买卖
	private boolean roleChoose = false;  //人物是否选择买卖
	private int tempH = 0; //游戏介绍的总高度
	
	private String pMessage;
	private boolean isProperty = false;
	private Image pImage = null;
	
	private boolean isJump = false;
	
	private boolean isSelectAttack = false;
	private boolean isRoleAttack = false;

	protected RPGCanvas(RPGMidlet midlet) { // 构造函数,初始类
		super(true);
		this.midlet = midlet;
		g = getGraphics();
		r = new Random();
//		t = new Thread(this);
		mroleProperty = new int[] { 0, 0, 0, 0, 0 }; // 分别表示等级,宝物,完成任务数,血气,宝物
		//		mroleProperty = new int[] { 1, 1, 1, 1, 1 }; // 为什么只有mroleproperty【4】才等于1

		vectormessage = new Vector();
		vectorpicture = new Vector();
		load = new Load();
		curmessage = null;
		missionmessage = null;
		curpicture = null;
		if (scene == 1)
			mrole = new Mainrole(load.imgrole, 16, 24, 50, 50, 80, 153);
		else if (scene == 2) {
			mrole = new Mainrole(load.imgrole, 16, 24, 80, 153);
			inputmode = 2;
		}

		lmscene1 = new LayerManager();
		lmscene2 = new LayerManager();

		setCommandListener(this);
		record = new SaveStateRecord("RPGRecord2");

		bgPlayer = new AudioPlayer("bg.mid", "audio/midi");
		// beatPlayer = new AudioPlayer("beat.mmf", "application/vnd.smaf");
		isFirstStart = true;

		gameState = GAME_MENU;
		menuState = MENU_START;

		try {
			// addendshowtalk();
			load.p.start();
		} catch (MediaException e) {
			e.printStackTrace();
		}
//		t.start();
	}

	public void stop() {
		t = null;
	}
	
	public void start(){
		t = new Thread(this);  //为什么需要加上对象参数this??当无this时无游戏画面
		t.start();
		System.out.println("Thread Start!");
	}
	
	//产生随机数
	int getrand(int m) {
		int n = r.nextInt();
		if (n < 0)
			n *= -1;
		n %= m;
		return n;
	}

	public void screenmove(int increasex, int increasey) { // 屏幕移动函数

		screenx = screenx + increasex;
		screeny = screeny + increasey;
		lastscreenx = increasex;
		lastscreeny = increasey;
	}

	void screenunmove() {// 屏幕负移动函数
		screenmove(-lastscreenx, -lastscreeny);
	}

	void draw() { // 绘画函数
		// 清屏
		if (!gameOver) {

			// 设置window
			if (!isAttack && !roleAttack && !roleBeat && !isSelectAttack) {
				g.setColor(255, 255, 255);
				g.fillRect(0, 0, getWidth(), getHeight());
				if (scene == 1) {  //加载场景一
					lmscene1.setViewWindow(screenx, screeny, screenwidth,screenheight);
					append();
					if(isBossDead)load.property[1].setVisible(false);
					lmscene1.paint(g, 0, 0);
					drawProperty();                     
				} 
				else if (scene == 2) {   //加载场景2
					mrole.setPosition(mrole.roomx, mrole.roomy);
					lmscene2.setViewWindow(0, 0, screenwidth, screenheight);
					append2();
					lmscene2.paint(g, 0, 0);
				}
			}

			if (missionmessage != null) {
				g.setColor(255, 255, 255);
				g.drawString(missionmessage, 0, screenheight, g.BOTTOM| g.LEFT);
			}

			// 显示对话
			drawmessage();

			if (showyesorno == true) {
				drawlist();          //显示选择框
			}

			if (sellerAsk) {                   //商人询问框 :买,卖,放弃  
				g.setColor(0, 0, 100);
				g.fillRect(0, getHeight() - 40, getWidth(), 40);
				g.setColor(255, 255, 128);
				g.drawImage(load.sellerbig, 0, screenheight - 40, g.TOP
						| g.LEFT);

				g.setColor(255, 255, 255);
				g.drawString(choose1, 60, getHeight() - 40, 0);
				g.drawString(choose2, 60, getHeight() - 30, 0);
				g.drawString(choose3, 60, screenheight - 20, 0);

				g.setColor(255, 255, 0);
//				g.fillArc(45, attackSelecty, 5, 5, 0, 360);
				g.drawImage(load.selectIcon,40, attackSelecty ,g.TOP|g.LEFT );
				Font ff = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
						Font.SIZE_SMALL);
				g.setFont(ff);
				g.setColor(255, 255, 255);
				g.drawString("Push FIRE", screenwidth, screenheight, g.BOTTOM
						| g.RIGHT);
				// sellerAsk = false;
				roleChoose = true;
			}

			if (isBuy) {          //角色选择买商品时的选择框:黄金-》血气,黄金-》宝物,放弃
				g.setColor(0, 0, 100);
				g.fillRect(0, getHeight() - 57, getWidth(), 57);

				g.drawImage(load.sellerbig, 0, getHeight() - 57, 0);
				g.setColor(255, 255, 255);

				g.drawString(choose1, 60, getHeight() - 40, 0);
				g.drawString(choose2, 60, getHeight() - 30, 0);
				g.drawString(choose3, 60, getHeight() - 20, 0);
				g.setColor(255, 255, 0);
//				g.fillArc(42, attackSelecty, 5, 5, 0, 360);
				g.drawImage(load.selectIcon, 40, attackSelecty, g.TOP|g.LEFT);
				forBuy = true;
			}

			if (isSell) {                //角色选择卖商品时的选择框:宝物-》黄金,放弃
				g.setColor(0, 0, 100);
				g.fillRect(0, getHeight() - 40, getWidth(), 40);

				g.drawImage(load.sellerbig, 0, getHeight() - 40, 0);
				g.setColor(255, 255, 255);

				g.drawString(choose1, 60, getHeight() - 30, 0);
				g.drawString(choose2, 60, getHeight() - 20, 0);
				g.setColor(255, 255, 0);
//				g.fillArc(42, selecty, 5, 5, 0, 360);
				g.drawImage(load.selectIcon, 40, selecty, g.TOP|g.LEFT);
				forSell = true;

			}

			if (isChoose) {                          //人物碰到npc时选择框:攻击,放弃
				g.setColor(0, 0, 100);
				g.fillRect(0, getHeight() - 57, getWidth(), 57);
				g.drawImage(load.hero, 0, getHeight() - 57, 0);
				g.setColor(255, 255, 128);

				g.drawString(choose1, 70, getHeight() - 30, 0);
				g.drawString(choose2, 70, getHeight() - 20, 0);

				g.setColor(255, 255, 0);
//				g.fillArc(52, selecty, 5, 5, 0, 360);
				g.drawImage(load.selectIcon, 50, selecty, g.TOP|g.LEFT);
				Font ff = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
						Font.SIZE_SMALL);
				g.setFont(ff);
				g.setColor(255, 255, 255);
				g.drawString("Push FIRE", screenwidth, screenheight, g.BOTTOM
						| g.RIGHT);
				
				g.setColor(0);
				g.drawRoundRect(0, screenheight - 65, 40, 5, 4, 2);
				g.setColor(0xB84909);
				g.fillRoundRect(0, screenheight - 65, roleBloodHeight, 5, 4, 2);
				g.setColor(255);
			}
			
			if(isJump){				
				g.setColor(255,255,255);
				g.fillRect((screenwidth - attackWidth) >> 1,
						(screenheight - attackHeight) >> 1, attackWidth, attackHeight);
//				g.setClip(mrole.x, mrole.y, 70, 64);
//				g.drawImage(load.heroJump, mrole.x - 70 * i, mrole.y, g.TOP|g.LEFT);
				g.setClip((screenwidth - attackWidth) >> 1,
						(screenheight - attackHeight) >> 1, attackWidth,attackHeight); 
				g.drawImage(load.heroJump, screenwidth / 2 - attackWidth* i, 
						screenheight >> 1, g.HCENTER | g.VCENTER);
				g.setClip(0, 0, screenwidth, screenheight);
				i ++;
				if(i == 6){
					isJump = false;
					isSelectAttack = false;
					i = 0;
					inputmode = 0;
					if (!warEnd) {          //当是boss的时候,根据人物等级不同,攻击力野不相同
						if (mroleProperty[0] <= 5)
							bossBlood -= 5;
						else if (mroleProperty[0] >= 11)
							bossBlood -= 10;
						else
							bossBlood -= mroleProperty[0];

						if (bossBlood >= 0) {
							isBossAttack = true;

							tempNum = getrand(4);
							switch (tempNum) {
							case 0:
								soldierWord = "看招:一击即中";
								blood = 4;
								attackWidth = 29;
								attackHeight = 32;
								break;
							case 1:
								soldierWord = "看招:所向披靡";
								attackWidth = 101;
								attackHeight = 76;
								blood = 3;
								break;
							case 2:
								soldierWord = "看招:怒海狂潮";
								blood = 5;
								attackWidth = 80;
								attackHeight = 80;
								break;
							case 3:
								soldierWord = "看招:天翻地覆";
								blood = 10;
								attackWidth = 78;
								attackHeight = 98;
								break;
							default:
								break;
							}
						} else
							isBossDead = true;
					}
				}
				g.setClip(0, 0, screenwidth, screenheight);
			}

			if (isAttack) {           //当人物选择攻击时,npc先进行攻击,在三招中随机选择一招        
				switch (tempNum) {
				case 0:
					soldierWord = "看招:一击即中";
					blood = 4;
					attackWidth = 29;
					attackHeight = 32;
					break;
				case 1:
					soldierWord = "看招:所向披靡";
					attackWidth = 101;
					attackHeight = 76;
					blood = 3;
					break;
				case 2:
					soldierWord = "看招:怒海狂潮";
					blood = 5;
					attackWidth = 80;
					attackHeight = 80;
					break;
				default:
					break;
				}
				g.setColor(255, 255, 255);
				g.fillRect(0, 0, screenwidth, screenheight);
				g.setColor(0, 0, 100);
				g.fillRect(0, 0, getWidth(), 50);
				g.drawImage(load.soldierbig, 0, 0, 0);
				Font f = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
						Font.SIZE_MEDIUM);
				g.setFont(f);
				g.setColor(255, 255, 255);
				g.drawString(soldierWord, 37, 0, 0);

				g.setClip((screenwidth - attackWidth) >> 1,
						(screenheight - attackHeight) >> 1, attackWidth,attackHeight); 
				g.drawImage(load.attack[tempNum], screenwidth / 2 - attackWidth* i, 
						screenheight >> 1, g.HCENTER | g.VCENTER);
				g.setClip(0, 0, screenwidth, screenheight);
				
				if (i == 6) {                     //招数六个画面播放完后
					isAttack = false;
					isSoldier = false;
//					roleAttack = true;
//					inputmode = 3;
					isChoose = true;
					inputmode = 1;
					choose1 = "普通攻击";
					choose2 = "魔法攻击";
					isSelectAttack = true;
					i = -1;
					load.npc[number].setVisible(false);
					randX = getrand(480);
					randY = getrand(450);   //在地图上随机生成相同的野怪
					load.npc[number] = new Npc(load.imgsoldier, 16, 24,
							load.npc[number].name, load.npc[number].message1,
							randX, randY, load.npc[number].message2,
							load.npc[number].img);
					mroleProperty[0]++;      //人物增加等级与野怪等级相同
					if (number == 3)
						mroleProperty[0]++;
					roleBloodHeight -= blood;
					// drawRoleAttack();
				}
				i++;
				
			}

			if (roleAttack) {            //人物进行攻击招数选择,共三种

⌨️ 快捷键说明

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