JAVA面向对象编程课程设计——泡泡堂(个人博客)

一、团队博客地址:JAVA面向对象编程课程设计——泡泡堂

二、个人负责模块或任务说明

  • GUI设计
  • 游戏界面类、地图类的实现(实现与Player类的交互)
  • 阿里巴巴扫描纠错
  • 团队博客编写

三、自己的代码提交记录

四、自己负责模块或任务详细说明

1.地图Field类

public class Field extends JPanel {
	

	private static final long serialVersionUID = 1L;
	int n = 1;
	
	/**存储地图的15*12个方格*/
	Box[][] boxes = new Box[15][12];


	/**初始化地图面板*/
	public Field(int n)
	{
		this.n = n;
		this.setLayout(null);
		this.setBounds(0, 0, 1200, 960);
	}


	/**覆盖add方法,添加新参数x,y*/
	public void add(Box b, int x, int y)
	{
		//将box添加进地图
		this.add(b);
		//保存box
		boxes[x][y] = b;
	}
	/**返回x,y坐标处的box值*/
	public Box getBoxbyLocation(int x, int y)

	{
		return boxes[x][y];
	}
	/**设置地图*/
	public void setField()

	{
		// 读取编号为n的地图文件
		File file = new File("map/" + n + ".txt");
		try {
			// 构造一个BufferedReader类来读取文件
			BufferedReader br = new BufferedReader(new FileReader(file));
			String s = null;
			int j = 0;
			while ((s = br.readLine()) != null) {
				String[] arr = s.split("\\s+");
				int i = 0;
				for (String ss : arr) {
					int ctemp = Integer.parseInt(ss);
					if (ctemp == 0) {
						Box temp = new Box(i, j);
						this.add(temp, i, j);
                                                //0为空地
					}
					// 1~5表示此处为可破坏的实体
					if (1 <= ctemp && ctemp <= 5)
					{
						Box temp = new Box(i, j, n, ctemp, true);
                                                //Box继承自Jlabel,初始化时会根据传参设置好该box的大小和位置
						this.add(temp, i, j);
					}
					// 6~10表示此处为不可破坏的实体
					if (6 <= ctemp && ctemp <= 10)
					{
						Box temp = new Box(i, j, n, ctemp, false);
						this.add(temp, i, j);
					}
					i++;
				}
				j++;
			}
			br.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**使图片自适应label标签大小*/
	public void setIcon(String file, JLabel com)
	{
		ImageIcon ico = new ImageIcon(file);
		//ico.getImage();
		Image temp = ico.getImage().getScaledInstance(com.getWidth(), com.getHeight(), Image.SCALE_DEFAULT);
                //获得一个适应于传入label大小的图片,此处传参是宽和高,还有缩放的方式,这里选择默认的方式
		ico = new ImageIcon(temp);
		com.setIcon(ico);
	}

}

Box类中的构造方法:

public Box(int x, int y, int n, int index, boolean canDestroy)// *存在*
	{
		this.canDestroy = canDestroy;
		// 设置该box大小、位置
		this.setBounds(80 * x, 80 * y, 80, 80);

		// 根据传入的参数设置图片
		setIcon("images/" + n + "/" + index + ".png", this);


		// 如果该box可以破坏
		if (canDestroy)
		{
			// 设置该box内藏的宝物
			setTreasure();

		}
	}
	/**不存在*/
	public Box(int x, int y)
	{
		// 设置该box为不存在
		isExist = false;
		// 设置该box大小、位置
		this.setBounds(80 * x, 80 * y, 80, 80);
		// 设置该box处图片为默认的图片(透明)
		setIcon("images/default.png", this);
	}

2.游戏界面GameFrame类

放入组件:

//取消默认布局
gameScreen.setLayout(null);
//设置地图面板大小、位置
map.setBounds(20,20,1200,960);
//取消默认布局
map.setLayout(null);
//设置面板背景为透明
map.setOpaque(false);
//生成地图
thismap=new Field(n);
//设置面板背景为透明
thismap.setOpaque(false);
//地图中加入玩家一
thismap.add(player1);
//地图中加入玩家二
thismap.add(player2);
//加载地图
thismap.setField();
//将加载好的地图加入map面板
map.add(thismap);
//将map面板加入主面板
//设置窗体大小,启动玩家移动线程
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
		int height = Toolkit.getDefaultToolkit().getScreenSize().height;
		int windowsWidth = 1500;
		int windowsHeight= 1050;
		gameFrame.setBounds((width - windowsWidth) / 2,(height - windowsHeight) / 2-25, windowsWidth, windowsHeight);
		setSize(windowsWidth,windowsHeight);
		background.getImage();
		Image temp=background.getImage().getScaledInstance(this.getWidth(),this.getHeight(),Image.SCALE_DEFAULT);  
		background=new ImageIcon(temp);  
		JLabel label = new JLabel(background); 
		label.setBounds(0, 0, this.getWidth(), this.getHeight());  
		gameScreen.add(label);
	    gameFrame.add(gameScreen);
	    gameFrame.setSize(windowsWidth, windowsHeight);
	    gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    gameFrame.setVisible(true);
	    moveThread1 m1 = new moveThread1();
		m1.start();
		moveThread2 m2 = new moveThread2();
		m2.start();

玩家移动线程:

	private class moveThread1 extends Thread {
		@Override
		public void run() {
			
				while (player1.isalive) {
					if(stopSign)
						break;
					if(pause){
						player1.move();
						colisionDetection(player1);
						if(player1.thisbomb!=null)
						{
							//判断玩家是否在当前炸弹上(一旦离开玩家当前放置的炸弹,便不可再次站上去)
							if(player1.thisbomb.isExistPlayer)
							{
								player1.onTheboom();
							}
						}
					}
				}
			
		}
	}

使用while循环实现持续监听,加入判断线程结束标志,当重新开始、返回主界面时,线程能够及时停止,避免再次启动的时候出现bug

碰撞检查

	public static void colisionDetection(Player pl)
	{
		int x = 1120;
		int y = 880;
		//出地图边境
		if(pl.getX()<0||pl.getX()>x||pl.getY()<0||pl.getY()>y)
		{
			pl.back();
			return;
		}
		int w = 15;
		int h = 12;
		for(int i=0;i<w;i++) {
			for(int j=0;j<h;j++)
			{
				try {
					Box temp=thismap.getBoxbyLocation(i,j);
					//碰撞检查
					if(temp.getRect().intersects(pl.getRect())&&temp.isExist)

					{
						//遇到箱子
						if(!temp.isdestroyshowT)

						{
							pl.back();
							return;
						}
						//遇到宝物
						else{
							switch(temp.treasureIndex){
							case 1:
								pl.pla.plusspeed();
								break;
							case 2:
								pl.pla.plusbombnum();
								break;
							case 3:
								pl.pla.pluspower();
								break;
							case 4:
								//无敌状态
								pl.invincible();
								break;
							case 5:
								pl.pla.pluslive();
								break;
								default:
									break;
							}
							//设置当前方格为[不存在]
							temp.isExist=false;
							//将当前方格设置为隐藏
							setIcon("images/default.png",temp);
						}
					}

					//遇到炸弹
					if(temp.isExistBomb&&!temp.isExistPlayer&&temp.getRect().intersects(pl.getRect()))
					{
						pl.back();
						return;
					}
				} catch (NullPointerException e) {

				}

			}
		}

	}

借助Rectangle类中的intersects方法来检测2个矩形是否相交,实现碰撞检查,再通过判断玩家前往的box的类型来判断下一步操作。

五、总结:

本次课设是多人组队课设,每个人负责一个模块,进度比一个人要来的快,遇到问题也能通过讨论得到合理解决。但在各模块交互,自己负责模块添加功能时也遇到了很多问题,自己的一点修改会影响这个项目的运行,作为组长,让我意识到不仅需要自己埋头写代码,更多需要和组员配合,了解进度,制定下一个目标,对我而言是一次宝贵的经验。比较遗憾的是,在界面和游戏本身的完成花了较多的时间,没有去尝试通过网络实现多人同台对战。

posted @ 2020-01-09 20:25  2276543  阅读(526)  评论(0编辑  收藏  举报