用java Swing做的小游戏"像素鸟"

最终效果




  整个项目都是基于swing实现的。窗是口将图片加载到JPanel面板,然后将面板添加到到JFrame窗口实现显示。

这个类是选择几只像素鸟的类,也是main函数里执行的方法,代码有详细的注释,这里就不废话了

public class select extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	Image background;//添加到窗口的背景图片
    Image title1;//添加到窗口的游戏名称图片
    JFrame jf; //选择小鸟的窗口
   JButton []b ;//按钮数组
   client t,t1,t2;//主游戏类
	public select(){
		
	    	jf = new JFrame();//实例化窗口
	    	jf.setTitle("请小心选择小鸟数量");//窗口的标题
	       jf.setSize(300, 300);//设置窗口大小
	        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗口关闭方式,关闭即退出程序
	        jf.setLocationRelativeTo(null);//设置窗口在屏幕中间显示
	        jf.setResizable(true);//窗口不可更改大小
	        jf.add(this);//将面板加入窗口
	       
        setLayout(null);//设置面板的布局为空,从而可以任意位置放置按钮
        final ImageIcon icon = new ImageIcon("Image/2.png");
        background = ((ImageIcon) icon).getImage();
        title1 = new ImageIcon("Image/title.png").getImage();	
        b = new JButton[3];
        //实例化按钮
        for(int i = 0;i < 3;i++)
       	b[i] = new JButton();
        //为按钮添加照片、设置背景位置
    	b[0].setIcon(new ImageIcon("Image/bird0_0.png"));
    	 b[0].setBounds(120,80,40,30);
    	 this.add(b[0]);
    	 //为第二个按钮添加照片、设置背景位置
        b[1].setIcon(new ImageIcon("bird3_2.png"));
         b[1].setBounds(95,130,100,33);
         this.add(b[1]);
        //外第三个按钮添加照片
        b[2].setIcon(new ImageIcon("bird3_3.png"));
         b[2].setBounds(70,185,146,35);
         this.add(b[2]);  
         //为第一个按钮添加点击事件
         b[0].addActionListener(new ActionListener(){
			public void actionPerformed(final ActionEvent e) {
				
				t = new client();//启动游戏类对象
				jf.dispose();//撤销当前窗口
		    	t.init1();//初始化即进入游戏
			} 
         });
         //为第二个按钮添加点击事件
         b[1].addActionListener(new ActionListener(){
 			public void actionPerformed(final ActionEvent e) {
 				jf.dispose();
 				 t = new client();
 		    	t.init2();
 			} 
          });
         //为第三个按钮添加点击事件
        b[2].addActionListener(new ActionListener(){
 			public void actionPerformed(final ActionEvent e) {
 				jf.dispose();
 				 t = new client();
 		    	t.init3();
 			} 
          });
         jf.setVisible(true);//设置窗口可见   
	}
	//启动窗口后会自动调用这个画画方法,将背景图片画到界面上
	public void paint(final Graphics g){
		super.paint(g);
		g.drawImage(background,0,0,300,300,this);
		g.drawImage(title1,55,20,174,48,this);
	}
}


client类,游戏主类。Main入口方法也放在了这里

public class client extends JPanel implements KeyListener{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Image background1,background2;  //定义两张图片作为背景
    private Plane pl;  //定义一个线程
    private pipe P[]=new pipe[300];//定义柱子数组对象
    ArrayList<pipe> list=new ArrayList<pipe>();//存放柱子的集合
    Random ran=new Random();
    public int k=0;
    public int score = 0;
    private bird b1,b2,b3;     //定义一个小鸟
    int flag;//判断调用哪个初始化函数,即创建几个小鸟
    private int x = 0;  //这个变量是用来改变小鸟的飞行状态,起到切换图片的作用
    public static  Music m;//背景音乐
    public static Music m2;//结束时的声音
    JFrame jf;
    public Image gameover =  new ImageIcon("Image/text_game_over.png").getImage();//游戏结束的图片
    //分别获取三只小鸟的散装飞行状态的图片
  	ImageIcon icon1 = new ImageIcon("Image/bird0_0.png");
  	ImageIcon icon2 = new ImageIcon("Image/bird0_1.png");
  	ImageIcon icon3 = new ImageIcon("Image/bird0_2.png");
  	ImageIcon icon4 = new ImageIcon("Image/bird1_0.png");
  	ImageIcon icon5 = new ImageIcon("Image/bird1_1.png");
  	ImageIcon icon6 = new ImageIcon("Image/bird1_2.png");
  	ImageIcon icon7 = new ImageIcon("Image/bird2_0.png");
  	ImageIcon icon8 = new ImageIcon("Image/bird2_1.png");
  	ImageIcon icon9 = new ImageIcon("Image/bird2_2.png");
  	
  	public boolean b = true;//判断是否进入画排行榜的变量
  	Font font = new Font("宋体",Font.BOLD,30);
  //存放从文件中获取的分数
  int ScoreArray[] = new int[300];
	JButton continueButton,outButton;
	RandomAccessFile Score;//定义随机流变量
	int nandu = 1;//游戏难度
    //实例化一个游戏类
    public static void main(String[] args) {
    
       new select();
    }
    
    public int produce() {
   	 return (int)(Math.random()*30 );
     }
    //主类的构造方法
    public client(){	
        
    	jf = new JFrame("请注意!即将开始游戏,控制三只小鸟的按钮依次时是:Q,W,E");//新建一个窗口
        jf.setSize(600, 393);//设置窗口大小
 
        jf.setLocationRelativeTo(null);//设置窗口在屏幕中间显示
        jf.setResizable(false);//窗口不可更改大小
        jf.add(this);//将面板加入窗口
        jf.setVisible(true);//设置窗口可见
        jf.addKeyListener(this);   //为窗口注册按键事件
        
        m=new Music("风中舞.WAV");//因为这个文件太大,在资源中我已经删掉了。想要背景音乐的话下载一个wav格式的音乐放到文件目录下。然后在这里输入资源名称即可
        m2=new Music("小黄人2.WAV");
        //通过ImageIcon类加载背景图片
        ImageIcon icon = new ImageIcon("Image/3.png");
       // ImageIcon icon1=new ImageIcon("Image/pipe_down.png");
     background1 = icon.getImage();
     background2 = icon.getImage();
     //给柱子初始化
     for(int i=0;i<300;i++){
    	 P[i]=new pipe(600+k,produce(),this);
    	 list.add(P[i]);
    	 k+=150;
     }   
    }
    
    //数据初始化方法
    //创建一只小鸟的时候调用
    public void init1()
    {   
       
    	flag  = 1;//设置小鸟数为1,为下面的画小鸟做准备
     b1 = new bird(0,100,this);//创建一个小鸟对象
     b1.setbird(icon1,icon2,icon3);
     pl = new Plane(background1,background2,0,0,this);//创建一个线程对象
     m.play();
    pl.start();  //
    }
    //两只小鸟一起飞时调用
    public void init2()
    {
    	
    	flag = 2;
     b1 = new bird(0,100,this);//创建一个小鸟对象
     b1.setbird(icon1,icon2,icon3);
     b2 = new bird(50,100,this);//创建一个小鸟对象
     b2.setbird(icon4,icon5,icon6);
     pl = new Plane(background1,background2,0,0,this);//创建一个线程对象
     m.play();
    pl.start();  //开始线程
    }
    //三只小鸟一起飞时调用
    public void init3()
    {	
    	flag = 3;
     b1 = new bird(0,100,this);//创建一个小鸟对象
     b1.setbird(icon1,icon2,icon3);
     b2 = new bird(50,100,this);//创建一个小鸟对象
     b2.setbird(icon4,icon5,icon6);
     b3 = new bird(100,100,this);//创建一个小鸟对象
     b3.setbird(icon7,icon8,icon9);
     pl = new Plane(background1,background2,0,0,this);//创建一个线程对象
     m.play();
    pl.start();  //开始线程
    
    }

    //JPanel面板的画图方法-------这个方法需不断地被执行,我们放在自己创建的一个线程里执行
    public void paint(Graphics g){
        super.paint(g); 
        g.drawImage(pl.background1, pl.x, pl.y, 600, 393, this);//画第一张背景图
        g.drawImage(pl.background2,599+pl.x, pl.y, 600, 393, this);//画第二张背景图
        //通过判断flag值来确定画几个小鸟
        String s = Integer.toString(score);
        String n = Integer.toString(nandu);
        this.drawBirdAndJump(g);
        //画柱子和柱子的移动
        for(int i=0;i<list.size();i++){
        	list.get(i).drawDown(g);
        	list.get(i).drawUp(g);
        	list.get(i).move();
        }  
        
        g.setColor(Color.RED);
        g.setFont(font);
        g.drawString("得分:"+s, 150, 25);   //画分数 
        g.setColor(Color.PINK);
        g.drawString("难度:"+n, 380, 25);
        this.isDead(g);
	       try {
     	 		this.showScore(g);
     	 	} catch (IOException e) {
     	 		// TODO Auto-generated catch block
     	 		e.printStackTrace();
     	 	}

    }
    public void   isDead(Graphics g){
    	//柱子和1只小鸟碰撞  
    	  if(flag==1){
          	for(int i = 0;i < list.size();i++){
          		if(b1.Getrect().intersects(list.get(i).GetDOWNrect()) ||//第一只鸟与上边界柱子相碰
          				b1.Getrect().intersects(list.get(i).GetUPrect())//第一只鸟与下边界柱子相碰
          				|| b1.gety() < 0 || b1.gety() > 393)//小鸟往上飞出窗口或者往下掉出窗口
          		{
          			 pl.setFlag(false);//柱子停止移动
          		 m.stop();//游戏结束时停止背景音乐
          			 g.drawImage(gameover,200,180,204,54,this);//画出游戏结束图片
          
          		}
          		
          	}
      
      }
          //2只小鸟时,小鸟与柱子的碰撞
          else if(flag==2){
          	for(int i = 0;i < list.size();i++){//
          		if(b1.Getrect().intersects(list.get(i).GetDOWNrect()) ||   
          				b1.Getrect().intersects(list.get(i).GetUPrect())
          				|| b2.Getrect().intersects(list.get(i).GetDOWNrect())
          				|| b2.Getrect().intersects(list.get(i).GetUPrect())
          				|| b1.gety() < 0 || b1.gety() > 393
          				|| b2.gety() < 0 || b2.gety() > 393)
          		{
          			 pl.setFlag(false);
          			 m.stop();//游戏结束时停止背景音乐
          			 g.drawImage(gameover,200,180,204,54,this);
          		}

          }
          }
          //三只小鸟时候的小鸟与柱子碰撞
          else if(flag==3){
            	for(int i = 0;i < list.size();i++){
          		if(b1.Getrect().intersects(list.get(i).GetDOWNrect()) ||
          				b1.Getrect().intersects(list.get(i).GetUPrect())
          				|| b2.Getrect().intersects(list.get(i).GetDOWNrect())
          				|| b2.Getrect().intersects(list.get(i).GetUPrect())
          				|| b3.Getrect().intersects(list.get(i).GetDOWNrect())
          				|| b3.Getrect().intersects(list.get(i).GetUPrect())
          				|| b1.gety() < 0 || b1.gety() > 393
          				|| b2.gety() < 0 || b2.gety() > 393
          				|| b3.gety() < 0 || b3.gety() > 393)
          				{
          			 pl.setFlag(false);
          			  m.stop();	//游戏结束时停止背景音乐
          			 g.drawImage(gameover,200,180,204,54,this);
          				}
            	}
      }
    	  if(pl.getFlag())
    	  {
          for(int i = 0;i < list.size();i++){
          	if(list.get(i).getUppipex() < 0){
          		//每十根柱子更改移动速度
          		if(score % 10 == 0 && score != 0){
          			pipe.setMoveSp();
          			nandu++;
          		}
          		list.remove(i);
          		  Music mus=new Music("小黄人1.WAV"); ;//定义多个过柱子时的笑声
          		mus.play();   	
          		score++ ;   		
          	}
          }
    	  }
    }
    /*
     * 画出排行榜
     * 画出当前分数的排行
     */
    public void showScore(Graphics g) throws IOException{
    	int max,sedmax,threemax;//三个变量保存分数的前三名
    	if(!pl.getFlag()&&b){
    		b = false;//避免线程刷新画面时重新进入浪费资源,设置为false
    		int i;
    		//创建随机流访问文件
    		//判断是几只小鸟,然后将分数存到不同的文件中
    		if(flag == 1)
    		 Score = new RandomAccessFile("scoreOneBird.dat","rw");
    		else if(flag == 2)
    			Score = new RandomAccessFile("scoreTwoBird.dat","rw");
    		else
    			Score = new RandomAccessFile("scoreThreeBird.dat","rw");
    		//将位置跳到文件末,存放分数
    		Score.seek(Score.length());
				Score.writeInt(score);
				//关闭文件
				Score.close();	
			 i =0;
				while(true){
					       //判断是在玩几只小鸟,然后打开不同的存分数文件
					if(flag == 1)
						  	Score = new RandomAccessFile("scoreOneBird.dat","rw");
					else if(flag == 2)
		    			Score = new RandomAccessFile("scoreTwoBird.dat","rw");
		    		else
		    			Score = new RandomAccessFile("scoreThreeBird.dat","rw");
							//每隔四个字节读取一个整形数
						  	Score.seek(i*4);
					//将分数保存到数组中
						ScoreArray[i] = Score.readInt();
						i++;
						//如果到文件末尾,退出循环
						if(Score.length() == i*4){
							break;
						
					}
				}
				//关闭文件
					Score.close();
			//初始化三个变量
			max = sedmax = threemax = 0;
			//将数组按顺序排序
			Arrays.sort(ScoreArray);
			//轻松获取前三大值
			max = ScoreArray[ScoreArray.length-1];
			sedmax = ScoreArray[ScoreArray.length-2];
			threemax = ScoreArray[ScoreArray.length-3];
			//记录排名,从末尾往前
			int count = ScoreArray.length;  
             for(i = 0;i < ScoreArray.length;i++)
             {
            	 //如果分数比数组里的数大,排名往前一位
            	 if(ScoreArray[i] < score )
            		 count--;
            	 //如果等0,说明是第一名
            	 if(count == 0)
            		 count = 1;
             }
             //三个整形转换成字符型
			String ScMax = Integer.toString(max);
			String ScSeMax = Integer.toString(sedmax);
			String ScThMax = Integer.toString(threemax);
			//设置字体大小、改变颜色、画出排名
		        g.setFont(font);
		        g.setColor(Color.MAGENTA);
		        g.drawString("当前排名:"+count,150, 90);
		        g.setColor(Color.ORANGE);
		        g.drawString("得分排名第一:"+ScMax, 150, 120);
		        g.setColor(Color.CYAN);
		        g.drawString("得分排名第二:"+ScSeMax, 150, 150);
		        g.setColor(Color.GREEN);
		        g.drawString("得分排名第三:"+ScThMax, 150, 180);
		        //实例两个按钮
		        continueButton = new JButton("重新开始");
		        outButton = new JButton("退出游戏");
		   //将按钮添加到面板上、设置背景颜色、出现的位置以及大小
		        this.add(continueButton);
		        this.add(outButton);
		        continueButton.setBackground(Color.green);
		        continueButton.setBounds(140,240,100,50);
		        outButton.setBackground(Color.CYAN);
		        outButton.setBounds(350,240,100,50);
		        
		        //为继续按钮添加点击事件
		        continueButton.addActionListener(new ActionListener(){
		 			public void actionPerformed(ActionEvent e) {
		 				jf.dispose();
		 		       new select();
		 			} 
		          });
		   //     为退出游戏按钮添加点击事件
		        outButton.addActionListener(new ActionListener(){
		    
					public void actionPerformed(ActionEvent e) {
						// TODO Auto-generated method stub
						jf.dispose();
					}
		        });
		        
    	}
    }
    public void drawBirdAndJump(Graphics g){
        //画一只小鸟
        if(flag == 1)
        {
        	jf.setTitle("单飞像素鸟        跳跃键:Q");
        	b1.draw(g,x);//调用小鸟对象的画图方法画一个小鸟
        }
        //flag=2 画2只小鸟
      else if(flag == 2)
      {
    	  jf.setTitle("双飞像素鸟      跳跃键:Q、W");
        b1.draw(g,x);
        b2.draw(g,x);
      }
        //画三只小鸟
      else
      {
    	  jf.setTitle("三飞像素鸟         跳跃键:Q、W、E");
        b1.draw(g,x);//调用小鸟对象的画图方法画一个小鸟
        b2.draw(g,x);
        b3.draw(g,x);
      }
        x++;//每次跑都改变小鸟飞行的图片
        if(flag == 1)
          b1.move();//小鸟往下掉的方法
        else if(flag == 2)
        {
        b1.move();
        b2.move();
        }
        else if(flag == 3){
        b1.move();//小鸟往下掉的方法
        b2.move();
        b3.move();
        }
        if(x == 3)//小鸟飞行有三张图片,循环变换
        	x = 0; 
    }
    //按下键盘时自动调用的方法
	public void keyPressed(KeyEvent e) {
	
	}
	//按下并且释放键盘时自动调用的方法
	public void keyReleased(KeyEvent e) {
		//通过flag值判断调用多少个小鸟的按键函数
		if(flag == 1)
		 b1.keyPressed1(e);//调用小鸟类的按键方法
		else if(flag == 2){
		 b1.keyPressed1(e);
		 b2.keyPressed2(e);
		}
		else{
		 b1.keyPressed1(e);//调用小鸟类的按键方法
		 b2.keyPressed2(e);
		 b3.keyPressed3(e);
		}
		
	}

线程类非常简单。只要一个死循环就行

public class Plane extends Thread {
	public Image background1, background2; // 定义两张背景

	public int x = 0; // 背景图片x坐标
	public int y = 0;// 背景图片y坐标
	public JPanel jp;// 定义一个面板
	public int movesp = 5;// 背景图的移动速度
	public boolean flag = true;
	public Music m = new Music("风中舞.WAV");
	public Music m2 = new Music("小黄人2.WAV");

	// 构造方法
	public Plane(Image background1, Image background2, int x, int y, JPanel jp) {
		m.play();
		this.background1 = background1;
		this.background2 = background2;
		this.x = x;
		this.y = y;
		this.jp = jp;// 将面板传进来主要是为了在线程中调用窗口面板的repaint
		// 方法,重画游戏窗口
	}

	public boolean setFlag(boolean flag) {
		this.flag = flag;
		return flag;
	}

	public boolean getFlag() {
		return flag;
	}

	public void run() {
		// 在线程中循环调用背景图的move方法,并且重画面板

		while (true) {
			if (flag) {
                                //移动就是通过不断刷新更改x,y值实现的
				jp.repaint();

			} else {
				m.stop();
				m2.play();
			}
			try {
				Thread.sleep(100);// 线程睡眠0.1秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

还有一个柱子类、封装的调用播放音乐的类非常非常简单这里就不放占用资源了。下载地址

像素鸟源代码下载下载后直接导入到myeclipse中就可以运行了噢


  • 10
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值