`
xichao1929
  • 浏览: 38856 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

我也做雷电

阅读更多

刚做完雷电小游戏,现在总结一下。雷电小游戏中我想核心的东西就是多线程的运用,做雷电就是为了能够熟练的使用多线程,加深对线程执行过程的理解。至于现在对于多线程有了一定的了解,但不能说已经记载了血液中,能够使用多线程做出雷电,是趁热打铁的原因,如果在过几天做的话,我估计就会麻烦很多了。所以自己不看书不行。

正在执行的程序成为进程,在一个进程中,有多个线程,其中有个主线程,就是主函数,这个主线程负责启动整个程序;程序里面还存在很多其他的线程,比如负责刷新的线程,加背景音乐的线程,在雷电中有发射子弹的线程,敌机进攻的线程等。他们的启动有对象调用start();方法开始,这些线程所要执行的内容放在run();方法中。

下面说一下做雷电游戏。这个雷电中,飞机的移动和子弹的发射可以同时进行,所以每一个都应该是线程,对方的飞机(不止一个,放在一个线程里面)对方飞机发射子弹(也放在一个线程里面)。这是最初的想法,很显然是对的,后面再加一句就是,由飞机来启动子弹线程,飞机的位置就是子弹的初始位置。当然一开始就是飞机移动一下就发射一个子弹,结果就是子弹太快了,然后改进了一下,飞机移动10下在发射一个子弹,这样看起来就比较舒服。

现在说一下玩家的情况,空格键控制子弹的发射,上下左右键控制飞机的运动,当然用的就是键盘监听器,关于它的使用方式是临时问的同学很简单。里面有三个方法keyTyped();keyPressed();keyReleased();用前两个来控制子弹的发射,空格键按下去发射子弹,弹起来结束发射。

代码   

	// 重写键盘的方法
	public void keyPressed(KeyEvent e) {
		 x0=0;
		 y0=0;
		isdisappear = false;
		ImageIcon  img,img1;
	    img1=addpic1();
		img = addmypic();
		// 按空格键控制发射子弹
		if (e.getKeyCode() == KeyEvent.VK_SPACE) {
			//重写设置子弹发射的位置
			  
			//调用子弹发射的方法
			isstart=true;
//			mymis.ismisstart=false;
//			mymis.ismisdis = false;
			 
		}           
		// 按左键向左移动
		if (e.getKeyCode() == KeyEvent.VK_LEFT) {
	        x0=-8;	
			if(isLeftOutbound){  
			
		     x0=0;
			}
			if(x<=0){
				isLeftOutbound=true;
			}
			if(x>0){
				isLeftOutbound=false;
			}
			
		}
		//按右键 向右移动
		if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
			x0=+8;
			if(isRightOutbound){
			 x0=0;
			}
			if(x>=650){
				isRightOutbound=true;
			 
			}
			if(x<650){
				isRightOutbound=false;
			}
		
		}
		//向上移动
		if (e.getKeyCode() == KeyEvent.VK_UP) {
			y0 =-8;
			if (isUpOutbound) {
              y0=0;
			}
			if (y  <= 60) {
				isUpOutbound = true;
			}
			if (y > 60) {
				isUpOutbound = false;
			}

		}
		//向下移动
		if (e.getKeyCode() == KeyEvent.VK_DOWN) {
			y0 =+8;
			if (isDownOutbound) {
              y0=0;
			}
			if (y  >= 490) {
				isDownOutbound = true;
			}
			if (y < 490) {
				isDownOutbound = false;
			}

		}
	  
  		 g.drawImage(img1.getImage(), x, y, 40, 40, null);
         g.drawImage(img.getImage(), x+=x0, y+=y0,40,40, null);
        
		//用空格键控制子弹的发射
		if (isstart) {
             
			minmis pm = new minmis(g, x, y,false );
			Thread pmh = new Thread(pm);// 包装成线程
			pmh.start();// 启动线程
			mymis.add(pm);
		 
			try {
				Thread.sleep(50);
			} catch (Exception d) {
				d.printStackTrace();
			}
			
		}
	 
		
	}
   //用空格键控制子弹的发射情况
	public void keyReleased(KeyEvent e) {
	if(e.getKeyCode()==KeyEvent.VK_SPACE){
		isdisappear = false;
		Drawliskey.isstart=false;
	//	mymis.ismisstart=true;
		 
		 
	}
	
	// Esc键退出
	if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
		System.exit(0);
	}

	}

                                                        

还有就是重绘的问题,当我们用一个线程去控制界面的刷新,就会出现屏幕狂闪的情况,这时我们就要用到双缓冲,非轻量级组件不需要双缓冲,就是不用update();函数,双缓冲的顺序是updatepaintrepaint,这些方法要放在轻量级组件中。在雷电中我是把所有的东西放在了JPanel上,所以,这些方法要在JPanel 的基础去调用。

代码

// 重写绘制自己的飞机
	public void paintmyair(Graphics g) {
		// 重新绘制自己的飞机
		ImageIcon myimg = Drawliskey.addmypic();
		g.drawImage(myimg.getImage(), Drawliskey.x, Drawliskey.y, 40, 40, null);

	}

	// 重写绘制敌人的飞机的方法
	public void paintair(Graphics g) {

		ImageIcon eneair = stealPlane.addpic();
		for (int j = 0; j < nair.size(); j++) {
			g.drawImage(eneair.getImage(), nair.get(j).x, nair.get(j).y, 50,
					50, null);
		}
	}

	// 重写绘制敌人子弹的方法
	public void paintenemmis(Graphics g) {
		// 重新绘制敌机的子弹
		ImageIcon misimg = enemis.addpicmis1();
		for (int i = 0; i < airmis.size(); i++) {

			g.drawImage(misimg.getImage(), airmis.get(i).x, airmis.get(i).y,
					10, 10, null);
		}

	}

	// 重新绘制玩家子弹的方法
	public void paintmymis(Graphics g) {
		 
		// 重新绘制玩家的子弹
		ImageIcon mymisimg = minmis.addpicmis();
		for (int m = 0; m < mymis.size(); m++) {
			g.drawImage(mymisimg.getImage(), mymis.get(m).x, mymis.get(m).y,
					10, 10, null);
		}

	}

	class MyPanel extends JPanel {

		// 重写update方法,先将窗体上的图形画在图片对象上,再一次性显示
		public void update(Graphics g) {

			// URL url = this.getClass().getResource("img/15.jpg");
			// javax.swing.ImageIcon img1 = new javax.swing.ImageIcon(url);
			ImageIcon img1;
			img1 = Drawliskey.addpic1();
			g.drawImage(img1.getImage(), 0, 0, 680, 535, null);
			if (offScreenImage == null) {
				// 截取窗体所在位置的图片
				offScreenImage = this.createImage(680, 535);
			}
			// 获得截取图片的画布
			Graphics gImage = offScreenImage.getGraphics();
			// 获取画布的底色并且使用这种颜色填充画布
			// Color c = Color.BLACK;
			gImage.drawImage(img1.getImage(), 0, 0, 680, 535, null);
			// gImage.fillRect(0, 0, 780, 640); //
			// 有清除上一步图像的功能,相当于gImage.clearRect(0,
			// // 0, WIDTH, HEIGHT)
			// 将截下的图片上的画布传给重绘函数,重绘函数只需要在截图的画布上绘制即可,不必在从底层绘制
			paint(gImage);

			// 将接下来的图片加载到窗体画布上去,才能看到每次画的效果
			g.drawImage(offScreenImage, 0, 0, null);
		}

		public void paint(Graphics g) {

			URL url = this.getClass().getResource("img/15.jpg");
			javax.swing.ImageIcon img = new javax.swing.ImageIcon(url);
			ImageIcon img1;
			img1 = Drawliskey.addpic1();
			g.drawImage(img1.getImage(), 0, 0, 680, 535, null);
			if (offScreenImage == null) {
				// 截取窗体所在位置的图片
				offScreenImage = this.createImage(685, 535);
			}
			// 获得截取图片的画布
			Graphics gImage = offScreenImage.getGraphics();
			// 获取画布的底色并且使用这种颜色填充画布
			// Color c = Color.BLACK;
			// gImage.setColor(c);
			// gImage.fillRect(0, 0, 780, 640);
			// 有清除上一步图像的功能,相当于gImage.clearRect(0,
			gImage.drawImage(img1.getImage(), 0, 0, 680, 535, null);
			super.paint(gImage);

			paintair(gImage);// 重新绘制敌机
			paintenemmis(gImage);// 重新绘制敌机的子弹
			paintmymis(gImage);// 重新玩家的子弹
			paintmyair(gImage); // 重新绘制自己的飞机
			// 将接下来的图片加载到窗体画布上去,才能看到每次画的效果
			g.drawImage(offScreenImage, 0, 0, null);
		}
	}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics