首頁>技術>
一、整體思路繼承窗體類,複寫窗體重新整理新增按鍵監聽遊戲結束介面王思聰類和熱狗類 移動軌跡計算判斷碰撞 音樂播放不斷重新整理窗體 處理細節二、編碼1.圖片

首先你要找到圖片,可以百度一張,然後用ps切開,再找一張背景圖片就搞定了(一張為活動角色,就是你方向鍵控制的角色,一個自動的角色,也就是“熱狗”)

活動角色

得分

你還需要一個載入圖片的工具類,可以使用getResource得到圖片的URL路徑,然後使用java自帶的工具類ImageIO來讀取圖片

public class GameUtil { 	public static Image getImage(String path){		URL url=GameUtil.class.getClassLoader().getResource(path);		BufferedImage img=null;		try {			img = ImageIO.read(url);		} catch (IOException e) {			e.printStackTrace();		}			return img;	}}
2.窗體

寫一個類來繼承窗體,為其設定寬高,位置,關閉設定,可否縮放大小

複寫它的更新和繪畫方法,以後要在裡面寫繪畫思聰和熱狗和碰撞判斷邏輯

			public void launchFrame(){		setSize(width,height);		setResizable(false);		setLocation(200,20);		setVisible(true);		addKeyListener(new KeyMoniter());		addWindowListener(new WindowAdapter(){			@Override			public void windowClosing(WindowEvent e) {				System.exit(0);			}		});	}         @Override	public void paint(Graphics graphics) {}	@Override	public void update(Graphics g){} 	class KeyMoniter extends KeyAdapter{		@Override		public void keyPressed(KeyEvent e) {	            //按鍵按下		}		@Override		public void keyReleased(KeyEvent e) {		    //按鍵抬起		}		}
3.思聰和熱狗

首先要有一個位置,還要能移動,其實也就是不斷的計算位置和把圖片畫上去的過程

定義一些思聰的屬性,並在構造方法中初始化這些屬性

	boolean left,right,down,up;		public int x,y,width,height;		Image img ; 	public Plane(String path,int x, int y){		this.img = GameUtil.getImage(img_path);		this.x = x;		this.y = y;		width = img.getWidth(null);		height = img.getWidth(null);		live = true;	}

把思聰畫上去

	public void draw(Graphics g){		if(live){			g.drawImage(img, x, y, null);			move();		}	}

接下來最重要的就是計算思聰的位置了,為什麼要把位置計算寫到畫思聰的方法裡呢?主要是考慮這樣的一種情況,如果你把方法計算寫到按鍵按下或者釋放裡面,那麼你想移動思聰的位置就得瘋狂按鍵盤,要想長按按鍵來控制移動就要吧移動方法寫到畫思聰的方法裡面,然後用按鍵的按下和釋放來控制是否移動。

移動的時候還要考慮到邊界的情況

	public void move(){		if(left&&x>=10){			x -= 10;		}				if(up&&y>=30){			y -= 10;		}		if(right&&x<=FeiJiGame.width-60){			x += 10;		}		if(down&&y<=FeiJiGame.height -60){			y += 10;		}	} 	public void KeyPressedControlDirection(KeyEvent e){		int key_code = e.getKeyCode();		if(key_code == 37){			left = true;		}		if(key_code == 38){			up = true;		}		if(key_code == 39){			right = true;		}		if(key_code == 40){			down = true;		}	} 	public void KeyRelasedControlDirection(KeyEvent e){		int key_code = e.getKeyCode();		if(key_code == 37){			left = false;		}		if(key_code == 38){			up =false;		}		if(key_code == 39){			right = false;		}		if(key_code == 40){			down = false;		}	}

最後提供兩個方法來改寫思聰的生存

對於熱狗類就簡單多了,就是讓它不斷的跑,不需要響應按鍵事件

定義一些屬性和在構造方法中初始化

	double speed=15;	double degree; 	public double x,y;	public int width,height;	Image img; 	public Bullet(String path){		img=GameUtil.getImage(img_path);		degree = Math.random()*Math.PI*2;		x=FeiJiGame.width/2;		y=FeiJiGame.height/2;		width = 10;		height = 10;	}

隨機的degree的用途是讓它們的初始方向不同,使用sin和cos函式來控制熱狗的移動,同時也要注意邊界

	public void draw(Graphics g){		g.drawImage(img, (int)x, (int)y, null);		x += speed*Math.cos(degree);		y += speed*Math.sin(degree); 		if(x>FeiJiGame.width-width||x<width){			degree=Math.PI-degree;		}		if(y>FeiJiGame.height-height||y<height){			degree=-degree;		}	}
4.碰撞檢測和音樂播放

在java的awt裡面有一個矩形類可以判斷兩個矩形是否有重疊部分,有重疊說明就碰撞上了

Rectangle bulletRectangle = new Rectangle((int)bullet.x,(int)bullet.y,bullet.width,bullet.height);Rectangle planeRectangle = new Rectangle(plane.x,plane.y,plane.width,plane.height);boolean collide= bulletRectangle.intersects(planeRectangle);

音樂播放可以使用第三方的庫,jl-1.0.1.jar,因為可能連續吃到熱狗,所以需要多執行緒播放音樂

	class MusicPlayer implements Runnable{		@Override		public void run() {			try {				new Player(new FileInputStream(FeiJiGame.class.getClassLoader().getResource("raw/music.mp3").getPath().substring(1))).play();			} catch (Exception e) {				e.printStackTrace();			}		}	}
5.完成

剩下的就是窗體的重新整理,這個可以開一個執行緒來做

	class PaintThread extends Thread {		@Override		public void run() {			while(!Thread.currentThread().isInterrupted()){				repaint();				try {					Thread.sleep(40);				} catch (InterruptedException e) {					Thread.currentThread().interrupt();				}			}		}		}

遊戲右上方要顯示現在的遊戲時間,結束也要顯示一些文字資訊,寫了一個工具類

使用font控制字型,graphics.setFont設定字型,drawString畫上去

	public void printInfo(Graphics g,String message,int size,int x,int y){		g.setColor(Color.white);		Font f = new Font("宋體",Font.BOLD,size);		g.setFont(f);		g.drawString(message, x,y);	}

遊戲結束時顯示一些資訊,根據時間判斷給出等級(可以隨意設定,自定義分數和等級)

	private void gameOver(Graphics graphics) {		printInfo(graphics,"GAME OVER",80,270,300);		int survivalTime = (int)(endTime.getTime()-starTime.getTime())/1000;		printInfo(graphics,"吃熱狗時間:"+survivalTime+"秒",40,300,400); 		switch(survivalTime/10){			case 1:				printInfo(graphics,"獨孤求敗",50,350,500);				break;			case 2:				printInfo(graphics,"登堂入室",50,350,500);				break;			case 3:				printInfo(graphics,"小有成就",50,350,500);				break;			default:				printInfo(graphics,"初入江湖",50,350,500);				break;		}		paintThread.interrupt();	}

在初始化窗體時要新增熱狗和開始重繪執行緒,開始計時

		for(int i=0;i<15;i++){			Bullet bullet = new Bullet("images/hotdog.png");			bulletList.add(bullet); 		}		starTime = new Date();		endTime = new Date();		paintThread=new PaintThread();		paintThread.start();

複寫繪畫和更新

        @Override	public void paint(Graphics graphics) {		graphics.drawImage(bg, 0, 0, null);		plane.draw(graphics);		endTime = new Date();		if(gameState){			for(int i=0;i<bulletList.size();i++){				Bullet bullet=bulletList.get(i);				bullet.draw(graphics); 				Rectangle bulletRectangle = new Rectangle((int)bullet.x,(int)bullet.y,bullet.width,bullet.height);				Rectangle planeRectangle = new Rectangle(plane.x,plane.y,plane.width,plane.height);				boolean collide= bulletRectangle.intersects(planeRectangle); 				if(collide){					if (bulletList.size()!=0){						executorService.execute(musicPlayer);						bulletList.remove(i);						if (bulletList.size()==0){							gameState = false;						}					}				}			}		}else {			endTime = new Date();			gameOver(graphics);			paintThread.interrupt();		} 		int count_time = (int)(endTime.getTime()-starTime.getTime())/1000;		printInfo(graphics,"你已經吃了"+count_time+"秒",20,750,50);	} 	Image ImageBuffer = null;  	Graphics GraImage = null;	@Override	public void update(Graphics g){	    ImageBuffer = createImage(this.getWidth(), this.getHeight());	    GraImage = ImageBuffer.getGraphics();	    paint(GraImage);	    GraImage.dispose();	    g.drawImage(ImageBuffer, 0, 0, this);	}  

在按鍵監聽裡面呼叫思聰的按鍵按下和釋放方法

	class KeyMoniter extends KeyAdapter{		@Override		public void keyPressed(KeyEvent e) {			plane.KeyPressedControlDirection(e);		}		@Override		public void keyReleased(KeyEvent e) {			plane.KeyRelasedControlDirection(e);		}		}

最後啟動遊戲

	public static void main(String[] args) {		FeiJiGame game = new FeiJiGame();		game.loadGame();	}
6.注意事項

6.1 在載入lib下依賴包的時候,不同開發工具的引入方式不同,這裡主要區別是eclipse和idea

6.2 在程式載入素材檔案(背景和音樂等)需要對路徑進行中文編碼處理,否則路徑會程式設計url編碼,導致載入失敗,如果路徑是純英文,就不需要考慮這些。

20
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 分散式資料庫中介軟體Mycat → 實現資料庫讀寫分離與高可用