JAVA貪吃蛇小遊戲分論(一)
引言:Java貪吃蛇小遊戲是一款非常經典的小遊戲,在總論中分析了我的貪吃蛇小遊戲的執行過程,以及貪吃蛇的演算法分析等等,對於貪吃蛇的移動原理,隨機點的出現等有了一定的瞭解,那麼,分論三篇將從我寫的程式碼出發,分析貪食蛇小遊戲的具體組成原理和程式碼實現,分論一主要說明貪吃蛇小遊戲的介面設計,貪吃蛇的設計,和隨機點出現等,分論二來分析貪吃蛇移動方式的分析,分論三主要介紹貪吃蛇小遊戲輔助類,即圓角按鈕和音樂類的實現。
(一)貪吃蛇小遊戲介面分析
介面是貪吃蛇小遊戲執行的地方,是遊戲中最基礎的元素,在Java中利用swing來介面設計,有三個介面,啟動介面,執行介面,和重啟介面,利用窗體JFrame來設計介面,為了讓窗體比較好看,需要加入圖片,圖片的路徑需要放在程式可引用的地方。如下面的程式碼就是在啟動介面中加入圖片。
//加入背景圖片 public void AddPicture() { ImageIcon img = new ImageIcon("F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\timg.jpg");//注意引用圖片的路徑。 JLabel Label= new JLabel(img); Label.setBounds(0,0,img.getIconWidth(),img.getIconHeight()); //設定大小 frame.getLayeredPane().add(Label,new Integer(Integer.MIN_VALUE)); //設定圖片底層和按鈕在容器中的順序 JPanel jp =(JPanel)frame.getContentPane(); jp.setOpaque(false); //設定透明與否 }
然後在窗體中加入各種元件,如按鈕,文字框和標籤等,需要給按鈕加入監聽器事件,不同的按鈕有不同的作用,如進入遊戲按鈕點選以後進入執行介面,並關閉啟動介面。
/*設定按鈕的監聽器事件 * 進入按鈕的監聽器事件的主要功能是當點選按鈕以後,程式關掉啟動介面,並轉入執行介面。 * 主要實現原理是定義一個新介面的類,作為執行介面,然後定義一個關掉啟動介面的方法,然後在監聽器事件中, * 呼叫關掉介面的方法,例項化執行介面 */ @Override public void actionPerformed(ActionEvent e) { new pushButtonMusic (); // TODO 自動生成的方法存根 closeThis(); //關掉新介面的方法 try { new Frame2 (); //例項化執行介面 } catch (InterruptedException e1) { // TODO 自動生成的 catch 塊 e1.printStackTrace(); } //建立新的窗體,以達到切換窗體的效果 } private void closeThis() { // TODO 自動生成的方法存根 frame.dispose();//關閉啟動介面的方法。 }
開始遊戲或者暫停遊戲的用來控制貪吃蛇的具體狀態。
//設定按鈕的監聽器事件
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自動生成的方法存根
//按開始鍵
if(e.getSource() == startButton) {
new pushButtonMusic ();
startFlag = true;
startButton.setEnabled(false);
stopButton.setEnabled(true);
將標籤,按鈕等放入窗體中,來實現程式和使用者的人機互動功能,具體的關於SWing知識在Java基礎片中說了很多,此外,在執行程式的時候,需要重新定義窗體的大小和位置, 因為不同電腦螢幕大小不同。窗體顯示的位置也一樣。
(二)貪吃蛇和隨機點分析
貪吃蛇小遊戲中最難設計的便是貪吃蛇和隨機點,那麼,如何設計貪吃蛇和隨機點呢?我們已經知道貪吃蛇是以陣列的形式來定義的,貪吃蛇包括兩個部分,設計部分和實現移動,也就是說,如何讓貪吃蛇出現在窗體中,怎麼樣實現移動。隨機點在窗體中按照隨機點座標來實現。
(1)貪吃蛇的設計
它是由什麼組成的?如何實現移動?我們可以把貪吃蛇的蛇身定義為一個數組,理解成一個集合,它有固定的起始元素,代表遊戲一開始時的蛇身。當貪吃蛇吃到點時,集合就新增一個元素,蛇的長度就加一,然後隨機點重新出現。
那麼,集合中的元素是什麼呢?要理解這個問題,首先得關注蛇身移動所處的環境。在JFrame窗體中,是由X、Y軸座標對位置進行區分。貪吃蛇的蛇身可以看做是一個一個聯絡緊密的點,在座標軸上顯示出來。每當朝某個方向移動時,蛇的座標就按照某個規律變化。例如,我們操控貪吃蛇向上移動時,蛇的全體座標的Y軸就減一;如果蛇的第一個座標與蛇身的某個座標重合,就代表貪吃蛇碰到自己;如果蛇的第一個座標碰到了邊界,蛇就撞牆。這就是貪吃蛇的本質。
我們來建立建立蛇身上每一個點的物件,蛇身就是由一個一個這樣的物件所組成的,那麼定義一個類,用來返回貪吃蛇的每個點的座標:
/*
* 定義一個類,用來描述貪吃蛇遊戲中的蛇,蛇身上的每一個點,通過建立snakeNode的物件,指定不同的X軸和Y軸的值,就能組成一個蛇身。
* 同時可以獲得蛇身上的x和y點座標,和顏色
*/
import java.awt.Color;
public class SnakeNode { //定義蛇身集合中的各個元素點,x,y。以及顏色三個蛇的關鍵組成
private int x;
private int y;
private Color color;
public int setX=20;
public int setY=20;
public SnakeNode() {
super();
}
public SnakeNode(int x, int y, Color color) {
super();
this.x = x;
this.y = y;
this.color = color;
}
//定義和返回x座標
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
//定義和返回y軸的座標
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
//定義和返回顏色
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
其次,貪吃蛇的定義,定義一個集合,來儲存蛇身上的各個點。 一個變數,用來表示隨機出現的點(貪吃蛇的目標),貪吃蛇單擊開始按鈕以後初始移動的方向,定義一個變數Length用來表示蛇的長度。
private ArrayList<SnakeNode> snake = new ArrayList<>();//定義蛇身的陣列集合
private int Direction;//定義蛇頭的方向
private int Length ;//定義蛇身的長度
private SnakeNode newNode = new SnakeNode(1,1,Color.BLACK);//定義隨機點
將貪吃蛇加入窗體中,需要定義貪吃蛇在窗體位置,這樣的話,執行程式在執行介面就會看到貪吃蛇。
snake.add(new SnakeNode(width/2,length/2 ,Color.red));
snake.add(new SnakeNode(width/2,length/2+1 ,Color.blue));
snake.add(new SnakeNode(width/2,length/2+2 ,Color.green));
Direction = 1;//定義初始方向為向上
Length = 3;//蛇身長度為3
CreateNode1();//產生隨機點
貪吃蛇的移動需要在一個範圍內,執行介面中有按鈕等其他元件,故而將貪吃蛇的移動範圍和元件區域分開也就是貪吃蛇撞到的牆體。變數width和length。我們將蛇身的移動範圍限制在X軸上0—15,Y軸上0~25,至於變數unit,稍後再進行分析
private final int length = 15;//定義活動範圍
private final int width = 25;//定義活動範圍
private final int unit = 45;//定義單位長度
上面分析了貪吃蛇從設計到實現的整個過程,總體來說,將貪吃蛇看成一個數組集合,需要定義一個類,來獲得貪吃蛇每一節身體的座標,也就是陣列的每一個數,因為貪吃蛇分為蛇頭,蛇身和蛇尾,每一個部分的設計不一樣。然後定義一些變數,用來儲存貪吃蛇的座標,初始方向和長度,然後將其加入到窗體中,這樣執行程式的時候就可以看到貪吃蛇了,此外,將執行介面劃分為兩個區域,元件區用來放各種元件,貪吃蛇執行區就是貪吃蛇執行的區域,撞到邊界即撞到牆體就會死亡。
(2)隨機點設計
createNode()是創造隨機點的方法,隨機點是定義在窗體中隨機的x和y座標決定。創造隨機點有哪些要求?首先,隨機點的範圍肯定不能超出限制,否則遊戲將無法繼續;其次,隨機點不能出現在蛇身上,也就是隨機點的座標不能和蛇身體上的任意座標相同,否則就會出現BUG。
public void CreateNode1() { //創造隨機點的方法
Boolean flag = true;
while(flag) {
newY1 = new Random().nextInt(15)+1; //定義隨機點的縱座標
newX1= new Random().nextInt(25)+1; //定義隨機點的橫座標
for(int x = 0; x < Length; x++) { // 不能出現在蛇身上,通過迴圈判斷是否與蛇身的點重合來產生隨機點
if(snake.get(x).getX() == newX1 && snake.get(x).getY() == newY1) {
flag = true;
break;
}
flag = false;
}
for(int i = 0; i < Length; i++) { //隨機點不能超出面板 ,確定面板的上下左右邊界,然後判斷隨機點是否超出邊界。
if(snake.get(i).getX()> 5&& snake.get(i).getX()<newX1 &&snake.get(i).getY() > 5
&& snake.get(i).getY()<newY1) {
flag = true;
break;
}
flag= false;
}
}
Color color = new Color(new Random().nextInt(255),new Random().nextInt(255),new Random().nextInt(255));
newNode.setColor(color);
newNode.setX(newX1);
newNode.setY(newY1);
}
通過上面的分析,我們已經能夠架構出貪吃蛇的基本框架,設計好介面,定義好貪吃蛇的形狀和隨機點,那麼, 如何顯示在介面上呢?swing圖形介面設計有Graphics類,可用來畫出自己想要的圖形, 定義影象類,畫出貪吃蛇移動的執行介面,如貪吃蛇的形狀,背景圖片,蛇頭蛇尾等 。描述蛇函式的主體形狀,隨機點的形狀和蛇的形狀 。
//定義影象類,畫出貪吃蛇移動的執行介面,如貪吃蛇的形狀,背景圖片,蛇頭蛇尾等
//描述蛇函式的主體形狀,隨機點的形狀和蛇的形狀
protected void paintComponent(Graphics g) {
super.paintComponent(g);//加背景
Image im=Toolkit.getDefaultToolkit().getImage("F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\background1.jpg");//將圖片存入相應的路徑
g.drawImage(im, 0, 0, this.getWidth(), this.getHeight(), this);
//畫出蛇頭,貪吃蛇在上下左右移動的時候蛇頭的方向也不一樣,故監聽貪吃蛇上下左右的移動,改變蛇頭的圖形。
if(direction ==1||Direction==1){ //貪吃蛇向上時
Toolkit toolup = this.getToolkit();
Image headup = toolup.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\up.png");
g.drawImage(headup,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
}else if(direction ==-1){//貪吃蛇向下時
Toolkit tooldown = this.getToolkit();
Image headdown = tooldown.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\down.png");
g.drawImage(headdown,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
}else if(direction ==2){//貪吃蛇向左時
Toolkit toolleft = this.getToolkit();
Image headleft = toolleft.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\left.png");
g.drawImage(headleft,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
}else if(direction ==-2){ //貪吃蛇向右時
Toolkit toolright = this.getToolkit();
Image headright = toolright.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\right.png");
g.drawImage(headright,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
}
//畫出食物的形狀
Toolkit tool1 = this.getToolkit();
Image food= tool1.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\food.png");
g.drawImage(food,newNode.getX()*unit, newNode.getY()*unit, unit, unit,this);
Toolkit tool2 = this.getToolkit();
Image food1= tool2.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\food.png");
g.drawImage(food1,newNode.getX()*unit, newNode.getY()*unit, unit, unit,this);
//繪製指定矩形的邊框。矩形的左邊和右邊位於 x 和 x + width。頂邊和底邊位於 y 和 y + height。使用圖形上下文的當前顏色繪製該矩形。
g.drawRect(40, 30, 1350, 810 );
for(int x = 1; x < Length-1; x++) { //利用迴圈,來繪製蛇身的形狀
g.setColor(snake.get(x).getColor());
g.fillOval(snake.get(x).getX()*unit, snake.get(x).getY()*unit, unit, unit); //給蛇的每一個節點畫橢圓
}
for(int x = Length-1; x < Length; x++) { // 來繪製蛇身的形狀
Toolkit toolright = this.getToolkit();
Image headright = toolright.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\body.png");
g.drawImage(headright,snake.get(x).getX()*unit, snake.get(x).getY()*unit, unit,unit,this);//利用迴圈,來繪製蛇的形狀
}
}