水果忍者游戏


水果忍者游戏
  此篇文章是在时间较为紧的情况之下写;不足之处、日后定当丰富之。。。。望见谅。
    做软件开发的同学应该知道:水果忍者游戏本身其实是个大随机:随机产生抛出水果、每个水果随机运动、、、而这一切使用最重要的就是线程的运用了。

    按照自己小组做出的水果忍者游戏的步骤:大至分为游戏选择界面--游戏界面--结束游戏的选择框界面。


   1、游戏选择界面:主要添加按钮及其动作命令;背景音乐,以及添加背景图片。
例如:

// 主界面的方法
	public void init() {
		this.setTitle("切水果");
		this.setSize(300, 250);
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		this.setResizable(false);

		// 增加一个容器,添加选择按钮
		JPanel jp = new JPanel();
		// 添加按钮
		JButton jb_start = new JButton("计时模式");
		jp.add(jb_start);
		
		// 设置一个间隔
		JLabel jl = new JLabel("   ");
		JButton jb1_close = new JButton();
		
		// 添加经典模式按钮
		JButton jb1_start = new JButton("经典模式");
		jp.add(jb1_start);
		
		// 设置动作命令
		jb1_close.setActionCommand("退出游戏");
		//设置开始按钮图片
		ImageIcon icon1=new ImageIcon("src/image/start.png");
		//获取图片大小
		int height1 = icon1.getIconHeight();
		int weight1 = icon1.getIconHeight();
		// 将按钮的大小设置成图片的大小
		jb_start.setPreferredSize(new Dimension(height1, weight1));
		
		// 设置退出游戏界面的图片
		ImageIcon icon = new ImageIcon("src/image/back.png");
		// 获取图片大小
		int height = icon.getIconHeight();
		int weight = icon.getIconHeight();
		// 将关闭按钮的大小设置成图片的大小
		jb1_close.setPreferredSize(new Dimension(height, weight));
		// 添加图片
		jb1_close.setIcon(icon);
		
		// 将开始按钮的大小设置成图片的大小
		jb_start.setPreferredSize(new Dimension(height1, weight1));
		// 添加图片
		jb_start.setIcon(icon1);
		// 将按钮添加到画板上
		jp.add(jb_start);
		jp.add(jb1_start);
		jp.add(jl);
		jp.add(jb1_close);

		// 添加容器到界面上
		this.add(jp, BorderLayout.SOUTH);
		this.setVisible(true);

		//实例化第一界面音乐对象
		MusicPlay2 mp=new MusicPlay2();
		//启动音乐线程
		mp.start();
		// 实例化监听器对象
        GoActionListener gal=new GoActionListener(this,mp);
	    //添加监听器
        jb_start.addActionListener(gal);
        jb1_close.addActionListener(gal);



接着是实现按钮的动作命令:如果命令是游戏模式时、其相应的执行命令中就会将第一界面关闭、调用游戏界面的方法
其代码如下:
 
/**
	 * 构造方法
	 * 
	 * @param m
	 *            游戏主界面
	 * @param ef
	 *            游戏结束界面
	 */
	public GoActionLis(MainLogin m, EndingFrame ef, String gameModel) {
		this.m = m;
		this.ef = ef;
		this.gameModel = gameModel;
	}

	public void actionPerformed(ActionEvent e) {
		// 如果点击的是开始游戏
		if (e.getActionCommand().equals("计时模式")) {
			// 实例化一个游戏主界面的对象
			MainLogin ml = new MainLogin(lo, count, ef, "计时模式");
			ml.LoginSh();
			// 关闭登陆界面的音乐
			lm.CloseMusic();
			// 播放背景音乐
			Music_Thread mt = new Music_Thread();
			mt.start();
		} else if (e.getActionCommand().equals("退出游戏")) {// 退出游戏判断
			System.exit(0);
		} else if (e.getActionCommand().equals("经典模式")) {// 判断是否进入经典模式
			// 实例化一个游戏主界面的对象
			MainLogin ml = new MainLogin(lo, count, ef, "经典模式");
			ml.LoginSh();
			// 关闭登陆界面的音乐
			lm.CloseMusic();
			// 播放背景音乐
			Music_Thread mt = new Music_Thread();
			mt.start();

		} else if (e.getActionCommand().equals("重新开始")) {
			// 关掉上一次游戏的界面
			m.dispose();
			// 表示进行过一次游戏
			count = 1;
			// 实例化一个游戏主界面的对象
			MainLogin ml = new MainLogin(lo, count, ef, gameModel);
			ml.LoginSh();
			// 播放背景音乐
			Music_Thread mt = new Music_Thread();
			mt.start();
		}
	}


接着进入游戏界面后,实例化抛出水果的线程、添加背景音乐、最复杂是就是在重绘画布中的水果运动线程添加、判断水果是否切到、切到水果后画出的水果图形、、、
需要提醒的一点:线程游戏一般会持续的闪烁、、所以,要想解决这种情况、我们需要使用 双缓冲:声明第二块画布,将所有画图都在次画布上实现。
例:

// 设置属性
		this.setTitle("水果忍者");
		System.out.println(width + "     " + height);
		this.setSize(new Dimension(width + 149, height));
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		this.setCursor(HAND_CURSOR);
		this.setResizable(false);
		this.setLayout(new BorderLayout());
		// 添加一个计数面板
		jp1 = new JPanel();
		jp1.setPreferredSize(new Dimension(149, height));
		jp1.setBackground(Color.PINK);
		// 添加分数
		label = new JLabel();
		// 设置窗体可见
		this.setVisible(true);
		// 获取画布
		g = this.getGraphics();
		//实例化一个鼠标监听器对象
		fruitListenr = new Fruit_MouseListener();
		this.addMouseMotionListener(fruitListenr);
		this.addMouseListener(fruitListenr);
		// 创建一个线程,用来持续抛出水果
		throw_thread = new FruitThrow_Thread(this, g, fruitListenr, gameModel);
		throw_thread.start();
		// 创建双缓冲
		image = this.createImage(width + 149, height);
		// 获取次画布
		gra = image.getGraphics();
		// 倒计时标签
		time_label = new JLabel();
		// 实例化倒计时线程
		TimeThread time_thread = new TimeThread(time_label, gameModel);
		time_thread.start();
		//实例化一个连切的线程
		Pummel_Thread pummel_thread = new Pummel_Thread();
		pummel_thread.start();
	}
	// 获取图片的Image的画布
	/**
	 * 重绘方法,水果和背景图片
	 */
	public void paint(Graphics g) {
		super.paint(gra);
		// 绘制背景图片
		gra.drawImage(icon_1.getImage(), 0, 0, this);
		// 获得数组
		fruitArray = throw_thread.getArray();
		// 实例化一个随即类对象
		Random rand = new Random();
		// 随机获取图片
		drawfruit = throw_thread.getDrawfruit();
		int ran = rand.nextInt(180);
		// 获得球的半径
		size = throw_thread.getSize();
		if (fruitArray != null) {
			// 获取球心坐标
			if (null != fruitArray && fruitArray.length != 0) {
				// 画出水果
				for (int i = 0; i < fruitArray.length; i++) {
					FruitThread fruit_thread = fruitArray[i];
					// 判断是否进行过一次游戏
					if (count == 1) {
						fruit_thread.score = 0;
						count = 2;
					}
					if (fruit_thread != null) {
						// 判断水果是否被切到
						boolean cut = fruit_thread.getCut();
						// 如果水果被切到,则画出两个被裁减成两半的图形
						if (cut) {
							// 判断是否切到弹
							if (icon2[drawfruit[i]][1] == icon2[9][1]
									|| icon2[drawfruit[i]][1] == icon2[8][1]) {
								// 绘制爆炸后的图片
								gra.drawImage(
										icon2[drawfruit[i]][1].getImage(),
										fruit_thread.getX(),
										fruit_thread.getY(), null);
							} else {
								gra.drawImage(
										icon2[drawfruit[i]][1].getImage(),
										fruit_thread.getX() + 30,
										fruit_thread.getY() + 40, null);
								gra.drawImage(
										icon2[drawfruit[i]][0].getImage(),
										fruit_thread.getX() - 30,
										fruit_thread.getY() - 40, null);
								gra.drawImage(blood_icon.getImage(),
										fruit_thread.a, fruit_thread.b, null);
							}
							score = fruit_thread.getScore();
						} else {// 没有切到,则画出完整的图形
							gra.drawImage(icon[drawfruit[i]].getImage(),
									fruit_thread.getX(), fruit_thread.getY(),
									null);
						}
					}
				}
			}
		}



游戏需要判断是否结束;这就需要添加判断:时间判断和切到炸个数的判断以及掉下水果数目的判断。。。这些方法可以在球运动过程中调用。


最后的游戏结束框界面中,添加两个选择按钮:继续游戏和结束游戏。
每个界面都有其相应的音乐线程、
然而,值得注意的是,每个水果线程掉下后,都应该将其break掉;不然会使游戏运行越来越卡。。。。。

对于此游戏的介绍确实过于简单、、、为此,提供了自己所写的游戏代码。需要者可以下载查看。。。。你会有想不到的收获。。但较为可惜的是没能上传音乐。。。

猜你喜欢

转载自glc.iteye.com/blog/1612895