初學嘛) ,不過總的來講這個程序仍是頗有意思的。這裏我從新再整理了一下,但願能幫助到其餘想要開發相似程序的朋友,共同進步!
曬一下效果圖:java
哈,仍是有模有樣的。左邊是本身寫的冒險島,右邊是真的冒險島。
畢竟也是個遊戲,方向鍵能夠控制人物移動,而後能夠攻擊,能夠打怪,升級,作任務。網絡
先說一下素材,有一個專門提供冒險島素材的紙娃娃系統,冒險島中各類素材均可以從這個網站中獲取:
http://www.maplesimulator.com/programs/bannedstory多線程
遊戲中顯示出這樣的界面效果,能夠用PS中的圖層來理解,所謂圖層就是含有文字或圖形等元素的膠片,一張張按順序疊放在一塊兒,組合起來造成頁面的最終效果。函數
而這個膠片,就是JAVA中的容器JPanel。JPanel能夠設置背景圖片,也能夠多個JPanel放置於一個JPanel中,就拿遊戲下方的狀態條來講:
整個狀態條就是一個JPanel,咱們就新建一個狀態條類測試
public class StatusBar extends JPanel
而後讓他繼承JPanel。
咱們給這個JPanel設置這樣的一個背景:
給JPanel設置背景的方法是重寫JPanel的paint函數,看下面代碼應該很清楚。字體
public void paint(Graphics g){ g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\狀態條\\狀態條.png"),0,0,this); }
接着,在這個JPanel上還要顯示等級的數字、血條、藍條、經驗條,以及一個系統按鈕(不過其實這個按鈕並不屬於StatusBar類,咱們只是讓他顯示在這個位置)。
這些都是StatusBar類的成員。咱們只須要在固定的位置將相應的成員顯示就能夠了。
先說這個顯示等級的數字,很顯然就是一個JLabel嘛,不過我用的不是JLabel。
依舊是在paint函數中,加入這樣一段:動畫
g.setColor(Color.WHITE); g.setFont(new Font(Font.DIALOG_INPUT, Font.BOLD, 25));//設置字體 g.drawString(Integer.toString(lv), 50,38);//等級
直接把字畫在JPanel上的相應位置就能夠了,顏色、字體、大小、字的內容、橫縱座標,就這些參數。能夠查看API文檔,這裏就不細說。網站
血條藍條經驗條,這三個條條是大部分網絡遊戲都有的東西,主要用來直觀的顯示玩家狀態,拿血條舉例子,看最前面的效果圖,當前血量800,總血量1000,因此血條的長度就是整個血槽的4/5,這樣一想,用進度條這種組件去實現血條藍條是很可行的,然而我查了才發現,JAVA中(至少是標準庫吧。。)並無進度條這個組件,因此仍是要本身去實現它。
仍是在paint函數中:this
g.setColor(Color.RED); //血條 g.fillRect(141, 23, (int)((double)hp/allhp*length), 15); g.setColor(Color.BLUE); //藍條 g.fillRect(340, 23, (int)((double)mp/allmp*length), 15); g.setColor(Color.YELLOW); //經驗條 g.fillRect(539, 23, (int)((double)exp/allexp*length), 15);
根據當前血量和總血量的比例去繪製相應長度相應顏色的矩形,這樣一來動態的血條藍條經驗條的主體部分就完成了,咱們還須要在上面顯示具體的血量和血總量:
有了前面繪製等級的經驗,咱們使用g.drawString函數就能夠了,不過爲了顯示的美觀嗎,咱們還須要考慮一些問題,文字的顯示是與血條右邊對其的,而繪製文字的參數中提供的參數是這樣的一組x,y並不能符合咱們右對其的要求。
因此我用了另一種很機智(shabi)的方法:spa
//數字比例6.7619 /[比例3 String hptxt="["+Integer.toString(hp)+"/"+Integer.toString(allhp)+"]"; int hptxtnuml=Integer.toString(hp).length()+Integer.toString(allhp).length();//血量數字顯示的數字長度 int hptxtx=272-(int)(hptxtnuml*6.7619);//相應橫座標 String mptxt="["+Integer.toString(mp)+"/"+Integer.toString(allmp)+"]"; int mptxtnuml=Integer.toString(mp).length()+Integer.toString(allmp).length();//藍量數字顯示的數字長度 int mptxtx=471-(int)(mptxtnuml*6.7619);//相應橫座標 String exptxt="["+Integer.toString(exp)+"/"+Integer.toString(allexp)+"]"; int exptxtnuml=Integer.toString(exp).length()+Integer.toString(allexp).length();//藍量數字顯示的數字長度 int exptxtx=670-(int)(exptxtnuml*6.7619);//相應橫座標
先把要繪製的字符串準備好,而後計算一下文本長度(這個長度是指真的長度。。顯示出來要幾個座標。。別問我怎麼測得,我用尺子量的。。),最後換算出相應的座標繪製。
至此,狀態條的顯示就完成了。在個人設計中,人物的屬性(血,藍,經驗,等級,攻擊力等)是直接放在狀態條類裏做爲成員變量的,換句話說,你玩遊戲玩的不是那我的物,你的全部數據都不存在人物的類裏,而是存在狀態條類裏,人物攻擊力高,一下秒掉怪物,那只是配合着狀態條裏的屬性顯示給玩家看而已~
咱們先把狀態條放到一邊,待會再來用它。
如今咱們要實現方向鍵控制人物移動。
依舊是前面圖層的思想,人物也是一個圖層。咱們建立一我的物類:
public class Obj extends JPanel
先來分析一下人物的動做,人物有個朝向,臉朝左,臉朝右,站着不動的時候有站着不動的姿式,走路的時候有走路的姿式,按上鍵若是能抓到繩子,有爬繩子的姿式,按下有趴着的姿式。因此Obj類中須要有一個變量來控制人物的狀態,(向左走、向右走、向左趴下等):
private int zhuangtai=2;//人物狀態
而後在繪製背景圖片的時候,switch(zhuangtai)來決定該繪製哪張圖片就能夠了。
咱們能夠寫一個設置狀態的函數,以便控制人物的時候使用:
public void setzhuangtai(int a)//設置狀態 { zhuangtai=a; }
這裏說明一下,人物站立的時候,並非一張靜止的圖片,而是提早準備好的GIF圖像,站立的時候顯示的就是天然擺手的動畫分鏡頭以下:
固然若是不想使用GIF圖像的話,能夠新建一個線程,專門在站立狀態控制人物擺手動畫的切換。
相似攻擊的動畫顯示也是如此。
咱們如今先來設想一下控制人物移動的思路:
首先人物這個圖層(JPanel)是顯示在窗口上的,主類繼承JFream
而後人物做爲主類的成員,就和建立一個JButton同樣的寫法
private Obj ren=new Obj(0,0);//建立角色
用兩個整形變量x,y來表明人物的座標
接下來就是將,xy做爲參數使用setBounds函數設置人物的顯示座標以及顯示大小。
對主窗口註冊鍵盤監聽和觸發事件:
咱們按下方向鍵後,好比說方向右鍵,調用Obj類中的setzhuangtai函數,修改人物狀態,再將x+5 (這個值本身定,值越大移動的越快)接着再次使用setBounds從新設置人物的顯示座標。而後調用repaint進行重繪。
這樣就能夠實現人物的移動了。我這裏沒有附具體代碼,由於我不是這樣寫的。。(噗!!)
在實際測試中,這樣去實現人物移動會引入一個很麻煩的問題——當你設置了遊戲地圖以後,控制人物移動會出現背景跟不上人物,有殘影的情形,具體的解決方案是使用雙緩衝技術,不過我有另外的思路解決了這個問題,何樂而不爲呢:
人物移動的時候,人物這個圖層後面的背景老是拖着以前的背景,使得顯示着很不協調,個人解決方案是設置人物這個圖層的大小的時候,讓他充滿整個屏幕,這樣的話,人物移動時,背景就是整個屏幕,而不用考慮舊背景的殘影問題了。不過這樣設計的話,人物移動的方式就要改變了,不能再是移動人物類的對象在主窗口中顯示的位置,由於人物類的對象在主窗口中已是全屏顯示了,不能再改變,改變的只能是人物的圖片,在人物類的這個JPanel中內部的位置。因此x,y這個座標也是存於人物類中。
private int zhuangtai=2;//人物狀態 //屏幕座標 private int x; private int y; public void setzhuangtai(int a)//設置狀態 { zhuangtai=a; } public void setxy(int m_x,int m_y) { x=m_x; y=m_y; } //人物在屏幕中移動 public void movex(int m_x) { x+=m_x; } public void movey(int m_y) { y+=m_y; }
顯示的地方就經過x和y的值來調整位置,不過仍是有一個地方要注意,顯示圖片時的座標參數是指以左上角爲起點的,可是每一張圖片的大小都不同,因此若是不加換算的話就會出現這樣的問題:
人物的顯示座標天然是要以腳爲座標,因此咱們對於每一張圖都要測定它的偏移(很幸運的是紙娃娃系統能夠直接導出偏移的值),而後顯示的時候根據偏移去計算換算後的座標。
paint函數以下:
public void paint(Graphics g)
{ switch(zhuangtai) { case 0:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\走路\\向右走0.png"),x-15,y-68,this);break; case 1:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\走路\\向右走1.png"),x-15,y-68,this);break; case 2:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\走路\\向右走2.png"),x-15,y-68,this);break; case 3:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\走路\\向右走3.png"),x-15,y-68,this);break; case 4:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\走路\\向左走0.png"),x-76,y-68,this);break; case 5:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\走路\\向左走1.png"),x-76,y-68,this);break; case 6:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\走路\\向左走2.png"),x-76,y-68,this);break; case 7:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\走路\\向左走3.png"),x-76,y-68,this);break; case 8:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\站立\\面朝右站.gif"),x-40,y-86,this);break; case 9:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\站立\\面朝左站.gif"),x-24,y-86,this);break; case 10:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\跳躍\\向右跳.png"),x-40,y-90,this);break; case 11:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\跳躍\\向左跳.png"),x-25,y-90,this);break; case 12:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\趴下\\面朝左趴下.png"),x-106,y-40,this);break; case 13:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角\\趴下\\面朝右趴下.png"),x,y-40,this);break; case 14:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\左\\0.png"),x-165,y-110,this);break; case 15:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\左\\1.png"),x-165,y-110,this);break; case 16:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\左\\2.png"),x-165,y-110,this);break; case 17:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\左\\3.png"),x-165,y-110,this);break; case 18:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\左\\4.png"),x-165,y-110,this);break; case 19:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\左\\5.png"),x-165,y-110,this);break; case 20:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\左\\6.png"),x-165,y-110,this);break; case 21:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\左\\7.png"),x-165,y-110,this);break; case 22:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\左\\8.png"),x-165,y-110,this);break; case 23:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\右\\0.png"),x-115,y-110,this);break; case 24:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\右\\1.png"),x-115,y-110,this);break; case 25:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\右\\2.png"),x-115,y-110,this);break; case 26:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\右\\3.png"),x-115,y-110,this);break; case 27:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\右\\4.png"),x-115,y-110,this);break; case 28:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\右\\5.png"),x-115,y-110,this);break; case 29:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\右\\6.png"),x-115,y-110,this);break; case 30:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\右\\7.png"),x-115,y-110,this);break; case 31:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\技能\\輕舞飛揚\\右\\8.png"),x-115,y-110,this);break; case 32:g.drawImage(Toolkit.getDefaultToolkit().getImage("F:\\Code\\JAVA\\MapleStory\\圖片素材\\主角