首先你要找到圖片,可以百度一張,然後用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編碼,導致載入失敗,如果路徑是純英文,就不需要考慮這些。