Java实现RPG游戏(mini版pokemon)

总体概述

游戏素材来源:游戏素材
java图形界面开发:Swing教程
RPG游戏人物移动等等:RPG
对战界面:回合制对战

这是本人在大二暑期做的课程设计,要求基于java实现一个RPG游戏,在此做一个记录,代码里许多实现也是参考网上许多大佬分享的例子(链接在上面贴出),再做出自己的修改,有许多不足的地方欢迎大家指出。

英雄与NPC的创建

先写一个抽象类,是所有角色的基类:包含基本的属性,名字,血量,蓝量,攻击力,防御力,等级等等;平a,技能,升级等等方法。

public abstract class Role {
	private String name;
	private double hp;
	private double maxHp;
	private double lastHp;
	private double mp;
	private double maxMp;
	private double lastMp;
	private int atk;
	private int def;
	private int lv;
	private int exp;
	private String bodypath;
	private String sName1;
	private String sName2;
	private String sName3;
	
	public abstract void attack(int skill,Role role);
	public abstract void skill1(Role role);
	public abstract void skill2();
	public abstract void skill3(Role role);
	public abstract void equipment(int i);
	public abstract void removeEqu(int i);
	public abstract void levelup();
	
	public Role(String name, double hp, double maxHp, double mp, double maxMp, int atk, int def, int lv,
			String bodypath, String sName1, String sName2, String sName3) {
		super();
		this.name = name;
		this.hp = hp;
		this.maxHp = maxHp;
		this.mp = mp;
		this.maxMp = maxMp;
		this.atk = atk;
		this.def = def;
		this.lv = lv;
		this.bodypath = bodypath;
		this.sName1 = sName1;
		this.sName2 = sName2;
		this.sName3 = sName3;
	}

	// get,set方法
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	......
	

}

继承Role类,实现主角

public class Hero extends Role {
	//实例化一个音效类
	Au a = new Au();

	public Hero() {
		super("皮卡丘", 100, 100, 100,100, 60, 20, 1, "src\\Image\\皮卡丘.png", "电光一闪","治疗", "十万伏特");
		this.setExp(0);
	}

	public void attack(int skill, Role role) {
		role.setLastHp(role.getHp());
		if(skill == 1) {
			skill1(role);
		}else if(skill == 2) {
			skill2();
		}else {
			skill3(role);
		}

	}

	public void skill1(Role role) {
		StartFrame.showMessage("我方使用"+this.getsName1());
		a.play(4);
		role.setLastHp(role.getHp());
		role.setHp(role.getHp()-this.getAtk()+role.getDef());

	}

	public void skill2() {
		this.setLastMp(this.getMp());
		this.setMp(this.getMp()-(0.3-0.01*this.getLv())*this.getMaxMp());
		if(this.getMp() <=0) {
			this.setMp(this.getLastMp());
			StartFrame.flag = false;
			StartFrame.showMessage("蓝量不足!");
			return;
		}else {
			StartFrame.showMessage("我方使用"+this.getsName2());
			a.play(6);
			this.setLastHp(this.getHp());
			this.setHp(this.getHp()+(this.getMaxHp()-this.getHp())*0.3);
		}

	}

	public void skill3(Role role) {
		this.setLastMp(this.getMp());
		this.setMp(this.getMp()-(0.7-0.03*this.getLv())*this.getMaxMp());
		if(this.getMp() <=0) {
			this.setMp(this.getLastMp());
			StartFrame.flag = false;
			StartFrame.showMessage("蓝量不足!");
			return;
		}else {
			StartFrame.showMessage("我方使用"+this.getsName3());
			a.play(5);
			role.setLastHp(role.getHp());
			role.setHp(role.getHp()-this.getAtk()*2+role.getDef());
		}

	}
	
	// 战斗前添加装备(老师要求有装备,(◔‸◔)所以简单的实现有些粗糙)
	public void equipment(int i) {
		if(i == 0) {
			this.setAtk(this.getAtk()+10);
		}else if(i == 1) {
			this.setDef(this.getDef()+10);
		}
	}
	
	// 战斗后卸掉装备
	public void removeEqu(int i) {
		if(i == 0) {
			this.setAtk(this.getAtk()-10);
		}else if(i == 1) {
			this.setDef(this.getDef()-10);
		}
	}
	
	// 升级
	public void levelup() {
		if((this.getExp() >= this.getLv()*(this.getLv()+1)) && (this.getLv() < 10)) {
			this.setLv(this.getLv()+1);
			this.setMaxHp(this.getMaxHp()+0.1*this.getMaxHp());
			this.setHp(this.getMaxHp());
			this.setMaxMp(this.getMaxMp()+0.05*this.getMaxMp());
			this.setMp(this.getMaxMp());
			this.setAtk(this.getAtk()+4);
			this.setDef(this.getDef()+2);
		}else {
			this.setHp(this.getMaxHp());
			this.setMp(this.getMaxMp());
		}
	}
	
}

其他NPC也是类似的方法,就不一个个贴了,NPC不会升级什么的,所以更简单一些。

图形化界面

图形化界面都是由Swing制作的,按钮,进度条等等控件都可以直接拖,还是很方便的。地图地形是本人写了一个循环一张张贴出来的,比较low,大家可以参考开头RPC连接文章中实现地图生成器来自由的实现地图。
在这里插入图片描述

public class MoveFrame extends JFrame {
	Role hero;
	private JPanel contentPane;
	NPC1 npc1 = new NPC1();
	NPC2 npc2 = new NPC2();
	NPC3 npc3 = new NPC3();
	Rectangle dragonRec = new Rectangle(0,0,100,100);
	Rectangle waterRec = new Rectangle(350,0,150,50);
	Rectangle frogRec = new Rectangle(400,150,50,50);
	Rectangle pikaRec;
	Pikachu pika;
	UpdateThread ut;
	static int map1[][] = new int[6][10];


	/**
	 * Create the frame.
	 * @throws InterruptedException 
	 * 
	 */
	public MoveFrame(Role hero) throws InterruptedException{
		this.hero = hero;
		hero.levelup();
		Pikachu.Update();
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setSize(500, 300);
		setLocationRelativeTo(null);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		JPanel panel = new 	MyPanel();
		panel.setBounds(0, 0, 484, 261);
		contentPane.add(panel);
		panel.setLayout(null);
		
		
		
		this.setVisible(true);
		this.addKeyListener(new KeyListener() {

			@Override
			public void keyPressed(KeyEvent e) {
				// TODO 自动生成的方法存根
				if(KeyEvent.VK_UP == e.getKeyCode()) {
					Pikachu.towards = 1;
					Pikachu.up = true;
				}else if(KeyEvent.VK_DOWN == e.getKeyCode()) {
					Pikachu.towards = 2;
					Pikachu.down = true;
				}else if(KeyEvent.VK_LEFT == e.getKeyCode()) {
					Pikachu.towards = 3;
					Pikachu.left = true;
				}else if(KeyEvent.VK_RIGHT == e.getKeyCode()) {
					Pikachu.towards = 4;
					Pikachu.right = true;
				}
			}

			@Override
			public void keyReleased(KeyEvent e) {
				// TODO 自动生成的方法存根
				if(KeyEvent.VK_UP == e.getKeyCode()) {
					Pikachu.up = false;
				}else if(KeyEvent.VK_DOWN == e.getKeyCode()) {
					Pikachu.down = false;
				}else if(KeyEvent.VK_LEFT == e.getKeyCode()) {
					Pikachu.left = false;
				}else if(KeyEvent.VK_RIGHT == e.getKeyCode()) {
					Pikachu.right = false;
				}
			}

			@Override
			public void keyTyped(KeyEvent e) {
				// TODO 自动生成的方法存根
				
			}
		});
		pika = new Pikachu();
		pika.start();
		ut = new UpdateThread(panel);
		ut.start();
	}
	
	public void openStart(int i) {
		pika.interrupt();
		//ut.interrupt();
		if(i == 1) {
			StartFrame sf = new StartFrame(hero,npc1);
			sf.setVisible(true);
		}else if(i == 2) {
			StartFrame sf = new StartFrame(hero,npc2);
			sf.setVisible(true);
		}else if(i == 3) {
			StartFrame sf = new StartFrame(hero,npc3);
			sf.setVisible(true);
		}
		this.dispose();
	}
	
	public boolean collision() {
		pikaRec = new Rectangle(Pikachu.x,Pikachu.y,Pikachu.width,Pikachu.height);
		if(dragonRec.intersects(pikaRec)) {
			openStart(1);
			return true;
		}else if(waterRec.intersects(pikaRec)) {
			openStart(2);
			return true;
		}else if(frogRec.intersects(pikaRec)) {
			openStart(3);
			return true;
		}
		return false;
	}
	
	class MyPanel extends JPanel {
		// 一张张贴出地图地形
		public void paint(Graphics g) {
			super.paint(g);
			for(int i=0;i<6;i++)
				for(int j=0;j<10;j++) {
					if(i == 2&&j == 2) {
						g.drawImage(Pictures.draw(0).getImage(), 50*j, 50*i, 50, 50, null);
						g.drawImage(Pictures.draw(22).getImage(), 50*j, 50*i, 50, 50, null);
					}else if(i <= 2&&j == 2) {
						g.drawImage(Pictures.draw(0).getImage(), 50*j, 50*i, 50, 50, null);
						g.drawImage(Pictures.draw(23).getImage(), 50*j, 50*i, 50, 50, null);
					}else if(i == 2&&j <= 2) {
						g.drawImage(Pictures.draw(0).getImage(), 50*j, 50*i, 50, 50, null);
						g.drawImage(Pictures.draw(24).getImage(), 50*j, 50*i, 50, 50, null);
					}else if(i < 2&&j < 2) {
						g.drawImage(Pictures.draw(25).getImage(), 50*j, 50*i, 50, 50, null);
					}else if(i == 1&&j == 6) {
						g.drawImage(Pictures.draw(0).getImage(), 50*j, 50*i, 50, 50, null);
						g.drawImage(Pictures.draw(17).getImage(), 50*j, 50*i, 50, 50, null);
					}else if(i <= 1&&j == 6) {
						g.drawImage(Pictures.draw(0).getImage(), 50*j, 50*i, 50, 50, null);
						g.drawImage(Pictures.draw(18).getImage(), 50*j, 50*i, 50, 50, null);
					}else if(i == 1&&j >= 6) {
						g.drawImage(Pictures.draw(0).getImage(), 50*j, 50*i, 50, 50, null);
						g.drawImage(Pictures.draw(19).getImage(), 50*j, 50*i, 50, 50, null);
					}else if(i < 1&&j > 6) {
						g.drawImage(Pictures.draw(20).getImage(), 50*j, 50*i, 50, 50, null);
					}else {
						g.drawImage(Pictures.draw(0).getImage(), 50*j, 50*i, 50, 50, null);
					}
				}
			
			Pikachu.myDraw(g);
			
			for(int i=3;i<6;i++)
				for(int j=0;j<10;j++) {
					if((i == 3&&j == 9)||(i == 4&&j>=5)) {
						g.drawImage(Pictures.draw(21).getImage(), 50*j, 50*i, 50, 50, null);
						}
				}
			//绘制三个NPC的位置
			g.drawImage(Pictures.draw(1).getImage(),50,0,50,50,null);
			
			g.drawImage(Pictures.draw(2).getImage(),350,0,50,50,null);
			
			g.drawImage(Pictures.draw(3).getImage(),400,150,50,50,null);
		}

	}
	
	class UpdateThread extends Thread {
		JPanel panel;
		public UpdateThread(JPanel panel) {
			this.panel = panel;
		}
		
		@Override
		public void run() {
			while(!Thread.currentThread().isInterrupted()){
				panel.repaint();
				if(collision()) {
					break;
				}
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

	}
}

移动效果可以参考开头RPG那位博主的文章,里面有实现玩家移动,地图生成器等等,地图生成器小弟当时比较菜没有实现,就跟着教程实现了移动的部分,主要先找到一张4*4的人物移动素材图,然后在循环里面根据键盘的输入切换这些图片达到移动的动画效果。
在这里插入图片描述

战斗过程

在这里插入图片描述
战斗界面其实就是进度条表示血蓝条,三个按钮发动技能,大部分代码Swing会自动生成,只要在按钮里添加触发的事件即可,其实就是按每个按钮调用主角类相应的技能方法,NPC的攻击使用随机数实现,大家可以自行调整来更改发动每个技能的概率。

战斗界面可以学习回合制对战这篇文章,里面还有通过延时实现血条逐渐下降的效果,还是很炫酷的。

主角攻击

// 不同的按钮调用主角类不同的技能即可
JButton btnNewButton = new JButton();
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				flag = true;
						try {
							attack_course(1);
						} catch (InterruptedException e) {
							// TODO 自动生成的 catch 块
							e.printStackTrace();
						}
			}
		});
		btnNewButton.setBounds(73, 255, 93, 23);
		btnNewButton.setText(role.getsName1());
		panel.add(btnNewButton);
		
		JButton btnNewButton_1 = new JButton();
		btnNewButton_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				flag = true;
						try {
							attack_course(2);
						} catch (InterruptedException e1) {
							// TODO 自动生成的 catch 块
							e1.printStackTrace();
						}
			}
		});
		btnNewButton_1.setBounds(176, 255, 93, 23);
		btnNewButton_1.setText(role.getsName2());
		panel.add(btnNewButton_1);
		
		JButton btnNewButton_2 = new JButton();
		btnNewButton_2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				flag = true;
						try {
							attack_course(3);
						} catch (InterruptedException e1) {
							// TODO 自动生成的 catch 块
							e1.printStackTrace();
						}
			}
		});

NPC攻击

	public void enemyattack(Role role,Role role2)  {
		int i;
		while(true) {
			i = (int)(Math.random()*8);
			if(i>=0&&i<=3) {
				role.skill1(role2);
				showMessage("敌方使用了"+role.getsName1());
				refreshHp(role,role2,progressBar_1,progressBar,blueBar_1,1,1000);
				break;
			}else if(i==4||i==5) {
				role.skill2();
				if(flag) {
					showMessage("敌方使用了"+role.getsName2());
					refreshHp(role,role2,progressBar_1,progressBar,blueBar_1,2,1000);
					break;
				}else {
					//System.out.println("治疗蓝量不足 重新选择");
					continue;
				}
			}else{
				role.skill3(role2);
				if(flag) {
					showMessage("敌方使用了"+role.getsName3());
					refreshHp(role,role2,progressBar_1,progressBar,blueBar_1,3,1000);
					break;
				}else {
					//System.out.println("大招蓝量不足 重新选择");
					continue;
				}
			}
		}
			
	}

结算界面

在这里插入图片描述
结算界面比较简单,控件拖拖拖就好了,在label里面显示相应的属性,然后存到sqlite数据库,大家也可以选择其他的数据库。

最后

这是一年多前写的东西了,现在看来编码习惯还有没有注释什么的看起来确实有点离谱哈哈,虽然有很多不会的地方都是借鉴大佬的,不过这次实践也是受益匪浅。为了增加游戏的趣味,我还加入了音效,以及调整游戏数值让主角和NPC战力更接近。
总而言之,还是很好的一次提升自己的机会,如果大家发现有什么不足之处,欢迎指出。

代码连接

上传的有点乱,代码在src/RPG中:https://gitee.com/sanguinedab/pokemon_mini

  • 8
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Pokemon数据集是一个包含了关于Pokemon(宠物小精灵)的信息的数据集。这个数据集中收集了数百种Pokemon的属性、能力、技能、种族值等详细信息,可以用来进行各种数据分析和机器学习任务。 这个数据集中的属性信息包括每只Pokemon的种类、身高、重量、颜色等等。能力信息包括每只Pokemon的生命值、攻击力、防御力、速度等等。技能信息包括每只Pokemon可以使用的特殊技能、物理技能和状态技能。种族值则是一种用来表示Pokemon基础能力值的指标,能够影响Pokemon在战斗中的表现。 通过对Pokemon数据集进行分析,我们可以了解每个种类Pokemon的平均属性值、能力分布和技能种类等等。比如,我们可以分析哪些Pokemon的攻击力和速度高,哪些Pokemon的特殊防御力比较低,以及它们之间的关联性等。这对于创作游戏策略、进行角色平衡的调整等方面都有着重要的作用。 此外,Pokemon数据集还可以用于机器学习的任务。我们可以利用这些数据训练模型来预测Pokemon的属性、种族值等信息,或者构建一个可以根据Pokemon的属性和技能来推荐最佳战斗队伍的模型。这些模型可以在游戏中用于AI对战、自动战斗等功能。 总之,Pokemon数据集是一个提供了Pokemon相关信息的数据集,对于理解和分析Pokemon的属性、能力以及进行相关的机器学习任务具有重要意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值