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);
		}
	}