JAVA遊戲開發-超炫酷貪喫蛇遊戲源碼及教程

一.前言

某日,看見隔壁家的小朋友在玩一款網絡爆款貪喫蛇遊戲,感覺很好玩。自己剛好正在學習JAVA編程,也想實現一個類似功能的遊戲Demo練手,在網上查看了不少源碼案例,全都是很古老的方塊式貪喫蛇遊戲案例,沒有想要的實現,因此自己動手實現一個JAVA版的貪喫蛇遊戲。

我在這個Dome完成之後重寫了這個遊戲的Android版,並重新更名爲《蛇王傳說》。也歡迎大家下載試玩。遊戲下載地址:https://www.pgyer.com/yGir

我的另一篇博客有Androd版本的遊戲介紹:https://blog.csdn.net/hawkol/article/details/90608813

二、實現效果

1.啓動界面 蛇頭會左右擺動,動態效果

1

2、遊戲主界面   地圖上有不同的食物,用鍵盤控制蛇在地圖上行走,每喫掉一個食物,蛇會自動生長一節

2

三、按鍵功能說明  左右鍵蛇轉向,上鍵蛇加速行走。

四、美工準備

因自己不會美工,很多圖都是從網上找的,然後用photoshop摳圖,按自己的設計思路,做成以下樣式。做片做的比較醜,就不放原圖了。

1、images 文件夾

3

2、foolds文件夾

4

3、snake文件夾

 

5

4、在s0,s1,s2,s3,s4文件夾分別放以下5張圖,可以做成不同顏色和樣式(也就是蛇的皮膚)

五、打開Eclipse新建HawkRetroSnaker 項目,目錄文件結構如下圖:

從目錄結構可以看出,此遊戲有5個JAVA類,分別是

Foods.java (食物),

Snake.java (蛇),

SnakePlayer.java (遊戲主程),

Tools.java (工具類),

UIGameStart.java (啓動時的Ui).

六、遊戲代碼:關鍵代碼地方都有註釋,我就不多囉嗦了,代碼寫的比較爛,只是爲了實現功能,有很多地方可以優化,大家也可提出自己的見解。

1.Foods.java

package com.hawkonline.retorsnaker;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.imageio.ImageIO;

public class Foods {
	
	private int imgID;//食物圖片D 以foodsX 
	private int drawX;// 圖塊顯示中心的X位置
	private int drawY;// 圖塊顯示中心的Y位置
	
	private int generateEnergy;//產生能量

	private  int offsetX;// 圖塊塊顯示的X位置偏移值-自動計算
	private  int offsetY;// 圖塊塊顯示的X位置偏移值-自動計算
	
	private BufferedImage imgFoods;//
	
	public Foods(int imgID, int drawX, int drawY, int generateEnergy) {
		super();

		this.imgID = imgID;
		this.drawX = drawX;
		this.drawY = drawY;
		this.generateEnergy = generateEnergy;
		
		//加載食物圖片
		try {
			imgFoods= ImageIO.read(new FileInputStream("images\\foods\\foods"+imgID+".png"));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		this.offsetX = imgFoods.getWidth()/2;
		this.offsetY = imgFoods.getHeight()/2;
	}
	
	//畫食物
	public void drawFoods(Graphics cg,int x,int y ){
		cg.drawImage(imgFoods, drawX-offsetX+x, drawY-offsetY+y, null);
		cg.setColor(Color.WHITE);
		//參照線-------------------
		cg.fillRect(drawX-1+x, drawY-1+y, 2, 2);
	}

	public Foods() {
		super();
	}

	public int getImgID() {
		return imgID;
	}

	public void setImgID(int imgID) {
		this.imgID = imgID;
	}

	public int getDrawX() {
		return drawX;
	}

	public void setDrawX(int drawX) {
		this.drawX = drawX;
	}

	public int getDrawY() {
		return drawY;
	}

	public void setDrawY(int drawY) {
		this.drawY = drawY;
	}

	public int getGenerateEnergy() {
		return generateEnergy;
	}

	public void setGenerateEnergy(int generateEnergy) {
		this.generateEnergy = generateEnergy;
	}

	public int getOffsetX() {
		return offsetX;
	}

	public void setOffsetX(int offsetX) {
		this.offsetX = offsetX;
	}

	public int getOffsetY() {
		return offsetY;
	}

	public void setOffsetY(int offsetY) {
		this.offsetY = offsetY;
	}
}

2.Snake.java

package com.hawkonline.retorsnaker;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;

import javax.imageio.ImageIO;

public class Snake {
	private Random rand = new Random();
	private int to=0;//自動移動模式標記蛇移動的方向,1左,2右
	
	// 蛇圖片相關顯示屬性
	private int step;// 步長
	private int offsetX;// 圖塊塊顯示的X位置偏移值-自動計算
	private int offsetY;// 圖塊塊顯示的X位置偏移值-自動計算
	private BufferedImage imgSnakeHead;// 蛇頭圖片
	private BufferedImage imgSnakeBody1;// 蛇身體奇數圖片
	private BufferedImage imgSnakeBody2;// 蛇身體偶數圖片
	private BufferedImage imgSnakeTait1;// 蛇尾巴圖片
	private BufferedImage imgSnakeTait2;// 蛇尾巴圖片
	private BufferedImage imgRotate;// 旋轉後的圖片

	// 蛇的屬值
	private int energy;// 喫豆得到的能量
	private int snakeLength;// 蛇的長度--默認3節,根椐能量獲得的多少自動生長

	// 蛇頭
	private int snakeHeadX;// 蛇頭X座標
	private int snakeHeadY;// 蛇頭Y座標
	private int snakeHeadDirection;// 蛇頭移動的方向
	private int snakeDisplayStyle;// 蛇顯示風格
	private boolean snakeIsDeath;//蛇死亡標記   True-生存, false=死亡

	// 蛇身體
	private int[] bodyX;// 蛇身體X座標
	private int[] bodyY;// 蛇身體Y座標
	private int[] bodyDirection;// 蛇身體方向

	// 構造函數
	public Snake(int snakeHeadX, int snakeHeadY, int snakeHeadDirection, int snakeDisplayStyle) {
		super();
		this.snakeHeadX = snakeHeadX;
		this.snakeHeadY = snakeHeadY;
		this.snakeHeadDirection = snakeHeadDirection;
		this.snakeDisplayStyle = snakeDisplayStyle;
		this.snakeIsDeath = true;//蛇死亡標記   True-生存, false=死亡

		snakeLength =6;

		// 加載圖片
		try {
			imgSnakeHead = ImageIO.read(new FileInputStream("images\\snake\\s" + snakeDisplayStyle + "\\head.png"));
			imgSnakeBody1 = ImageIO.read(new FileInputStream("images\\snake\\s" + snakeDisplayStyle + "\\body1.png"));
			imgSnakeBody2 = ImageIO.read(new FileInputStream("images\\snake\\s" + snakeDisplayStyle + "\\body2.png"));
			imgSnakeTait1 = ImageIO.read(new FileInputStream("images\\snake\\s" + snakeDisplayStyle + "\\tait1.png"));
			imgSnakeTait2 = ImageIO.read(new FileInputStream("images\\snake\\s" + snakeDisplayStyle + "\\tait2.png"));

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		this.offsetX =imgSnakeHead.getWidth()/2;
		this.offsetY =imgSnakeHead.getHeight()/2;
		this.step = 8;

		// 蛇身體-構造時爲3節
		bodyX = new int[snakeLength];
		bodyY = new int[snakeLength];
		bodyDirection = new int[snakeLength];

		for (int i = 0; i < snakeLength; i++) {
			bodyX[i] = snakeHeadX - (i + 1) * step;
			bodyY[i] = snakeHeadY;
			bodyDirection[i] = 0;
		}

	}

	// 畫蛇
	public void snakeShow(Graphics cg,int x,int y) {

		// 畫蛇身體
		for (int i = snakeLength - 1; i >= 0; i--) {
			if (i == snakeLength - 1) {// 畫蛇尾
				if ((i % 2 == 0)) {
					imgRotate = Tools.rotateImage(imgSnakeTait1, bodyDirection[i]);
				} else {
					imgRotate = Tools.rotateImage(imgSnakeTait2, bodyDirection[i]);
				}

			} else {
				// 畫蛇身體
				if ((i % 2) == 0) {
					imgRotate = Tools.rotateImage(imgSnakeBody1, bodyDirection[i]);
				} else {
					imgRotate = Tools.rotateImage(imgSnakeBody2, bodyDirection[i]);
				}

			}
			cg.drawImage(imgRotate, bodyX[i] - offsetX+x, bodyY[i] - offsetY+y,null);
			// 參照線-------------------
			cg.setColor(Color.WHITE);
			cg.fillRect(bodyX[i] - 1+x, bodyY[i] - 1+y, 2, 2);
		}

		// 畫蛇頭
		imgRotate = Tools.rotateImage(imgSnakeHead, snakeHeadDirection);
		cg.drawImage(imgRotate, snakeHeadX - offsetX+x, snakeHeadY - offsetY+y,null);

		// 參照線-------------------
		cg.setColor(Color.WHITE);
		cg.fillRect(snakeHeadX - 1+x, snakeHeadY - 1+y, 2, 2);
		
		
		
		cg.setColor(Color.BLUE);
		int sX = (int) (snakeHeadX + 150 * Math.cos(snakeHeadDirection * 3.14 / 180));
		int sY = (int) (snakeHeadY + 150 * Math.sin(snakeHeadDirection * 3.14 / 180));
		cg.fillRect(sX - 1+x, sY - 1+y, 2, 2);
		
		sX = (int) (snakeHeadX + 100 * Math.cos((snakeHeadDirection+45) * 3.14 / 180));
		sY = (int) (snakeHeadY + 100 * Math.sin((snakeHeadDirection+45) * 3.14 / 180));
		cg.fillRect(sX - 1+x, sY - 1+y, 2, 2);
		sX = (int) (snakeHeadX + 100 * Math.cos((snakeHeadDirection-45) * 3.14 / 180));
		sY = (int) (snakeHeadY + 100 * Math.sin((snakeHeadDirection-45) * 3.14 / 180));
		cg.fillRect(sX - 1+x, sY - 1+y, 2, 2);
		// 參照線-------------------
		cg.setColor(Color.WHITE);
		cg.fillRect(snakeHeadX - 1+x, snakeHeadY - 1+y, 2, 2);
		
		

	}
	public void snakeAutoMove(){
		// 蛇智能移動方案3
		//蛇下一步的位置
		int sX = (int) (snakeHeadX + 150 * Math.cos(snakeHeadDirection * 3.14 / 180));
		int sY = (int) (snakeHeadY + 150 * Math.sin(snakeHeadDirection * 3.14 / 180));
		
		//蛇死亡了
		if(sX<=20||sX>=(Tools.MAP_X-20)||sY<=20||sY>=(Tools.MAP_Y-20)){
			boolean isL=false,isR=false;
			//看下左邊45度會不會死
			sX = (int) (snakeHeadX + 100 * Math.cos((snakeHeadDirection+45) * 3.14 / 180));
			sY = (int) (snakeHeadY + 100 * Math.sin((snakeHeadDirection+45) * 3.14 / 180));
			if(sX<=20||sX>=(Tools.MAP_X-20)||sY<=20||sY>=(Tools.MAP_Y-20)){
				isL=true;
			}
			//看下左邊45度會不會死
			sX = (int) (snakeHeadX + 100 * Math.cos((snakeHeadDirection-45) * 3.14 / 180));
			sY = (int) (snakeHeadY + 100 * Math.sin((snakeHeadDirection-45) * 3.14 / 180));
			if(sX<=20||sX>=(Tools.MAP_X-15)||sY<=20||sY>=(Tools.MAP_Y-15)){
				isR=true;
			}
			
			//左右死
			if((isL)&&(isL)){
				if(rand.nextInt(1)==1){
					snakeHeadDirection+=(rand.nextInt(5)+20);//增大旋轉角度
					to=1;
				}else{
					snakeHeadDirection-=(rand.nextInt(5)+20);//增大旋轉角度
					to=2;
				}
			}else if(isL){
				snakeHeadDirection-=(rand.nextInt(5)+5);//增大旋轉角度
				to=2;
			}else{
				snakeHeadDirection+=(rand.nextInt(5)+5);//增大旋轉角度
				to=1;
			}
		}else{
			if(rand.nextInt(rand.nextInt(20)+10)==1){
				to=rand.nextInt(3);
			}
			if (to==1) snakeHeadDirection+=(rand.nextInt(5)+2);
			if (to==2) snakeHeadDirection-=(rand.nextInt(5)+2);
		}
		snakeMove();


		
	}
	// 蛇移動-按照設置的方向前行
	public void snakeMove() {
		if (snakeIsDeath) {
			// 蛇的後一節的值繼承前一節的值
			for (int i = snakeLength - 1; i > 0; i--) {
				bodyX[i] = bodyX[i - 1];
				bodyY[i] = bodyY[i - 1];
				bodyDirection[i] = bodyDirection[i - 1];
			}
			// 第一節的值繼承蛇頭的值
			bodyX[0] = snakeHeadX;
			bodyY[0] = snakeHeadY;
			bodyDirection[0] = snakeHeadDirection;

			snakeHeadX = (int) (snakeHeadX + step * Math.cos(snakeHeadDirection * 3.14 / 180));
			snakeHeadY = (int) (snakeHeadY + step * Math.sin(snakeHeadDirection * 3.14 / 180));
		}

	}

	// 蛇生長--數組自動擴容1節
	public void snakGrow() {

		snakeLength = snakeLength + 1;

		if (snakeLength > bodyX.length) {
			bodyX = Arrays.copyOf(bodyX, snakeLength);
			bodyY = Arrays.copyOf(bodyY, snakeLength);
			bodyDirection = Arrays.copyOf(bodyDirection, snakeLength);
		}

	}

	// 蛇死亡
	public void snakeDeath() {
		this.snakeIsDeath = false;//蛇死亡標記   True-生存, false=死亡
		// 隨機數--產生蛇塊斷裂
		Random rand = new Random();
		for (int i = 0; i < snakeLength; i++) {
			bodyX[i] = bodyX[i] + rand.nextInt(step * 2) - rand.nextInt(step * 2);
			bodyY[i] = bodyY[i] + rand.nextInt(step * 2) - rand.nextInt(step * 2);
			bodyDirection[i] = bodyDirection[i] + rand.nextInt(360);
		}
		//snakeHeadX = snakeHeadX + rand.nextInt(step) - rand.nextInt(step);
		//snakeHeadY = snakeHeadY + rand.nextInt(step) - rand.nextInt(step);
		snakeHeadX = (int) (snakeHeadX + step * Math.cos(snakeHeadDirection * 3.14 / 180));
		snakeHeadY = (int) (snakeHeadY + step * Math.sin(snakeHeadDirection * 3.14 / 180));
	}


	// get---- set-----
	public int getSnakeHeadDirection() {
		return snakeHeadDirection;
	}

	public void setSnakeHeadDirection(int snakeHeadDirection) {
		this.snakeHeadDirection = snakeHeadDirection;
	}

	public int getSnakeHeadX() {
		return snakeHeadX;
	}

	public void setSnakeHeadX(int snakeHeadX) {
		this.snakeHeadX = snakeHeadX;
	}

	public int getSnakeHeadY() {
		return snakeHeadY;
	}

	public void setSnakeHeadY(int snakeHeadY) {
		this.snakeHeadY = snakeHeadY;
	}

	public boolean getSnakIsDeath() {
		return snakeIsDeath;
	}

	public boolean isSnakeIsDeath() {
		return snakeIsDeath;
	}

	public void setSnakeIsDeath(boolean snakeIsDeath) {
		this.snakeIsDeath = snakeIsDeath;
	}

	public int getEnergy() {
		return energy;
	}

	public void setEnergy(int energy) {
		this.energy = energy;
		
		if((energy-5)>=0){//每獲取5點能量,蛇生長一節(12-5)>=0
			this.snakGrow();//蛇生長
			this.energy=this.energy-5;
		}
	}

	public int getSnakeLength() {
		return snakeLength;
	}

	public void setSnakeLength(int snakeLength) {
		this.snakeLength = snakeLength;
	}

	public int getSnakeDisplayStyle() {
		return snakeDisplayStyle;
	}

	public void setSnakeDisplayStyle(int snakeDisplayStyle) {
		this.snakeDisplayStyle = snakeDisplayStyle;
	}

}

 

3.SnakePlayer.java

package com.hawkonline.retorsnaker;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;

public class SnakePlayer  extends JFrame implements Runnable, KeyListener{
	Random rand = new Random();
	private int runGame=0;
	
	//UI
	private UIGameStart uiGameStart=null;
	
	private int inputSleep=80;//線程執行間隔時長

	private int drawMapX,drawMapY;
	
	private static BufferedImage bfMap= new BufferedImage(Tools.MAP_X, Tools.MAP_Y, BufferedImage.TYPE_3BYTE_BGR); // 創建一張1920*1080的地圖源圖
	
    private static BufferedImage bfGameMap = new BufferedImage(Tools.SCREEN_X, Tools.SCREEN_Y, BufferedImage.TYPE_3BYTE_BGR); // 創建一張1920*1080的緩衝圖片
    private static Graphics bfGameMapGraphics =bfGameMap.getGraphics();// 獲取緩衝圖片的畫筆
    private BufferedImage imgDisplayInformation=null;
    private BufferedImage imeGameOver=null;
    
    private Foods []foods=null;//小圓點食物
    
    private Snake snake=null;//蛇
    //private Snake enemy=null;

	public SnakePlayer() {
		
		this.setTitle(Tools.GameName);
		// 設置框架的大小
		this.setSize(Tools.SCREEN_X, Tools.SCREEN_Y);
		 // 設置框架大小可以改變
		this.setResizable(false);
		//設置窗體居中顯示
		this.setLocationRelativeTo(null);
      // 設置點擊關閉按鈕 關閉界面
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//設置GUI的窗口圖標
		ImageIcon snakeIcon = new ImageIcon("images\\snakeIcon.png");
		this.setIconImage(snakeIcon.getImage());
		// 允許顯示遊戲界面
		this.setVisible(true); 
		// 添加鍵盤監聽器  
	    this.addKeyListener(this);
	    // 添加鼠標監聽器 

        //鼠標樣式
		this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
	    //創建UI界面
	    uiGameStart=new UIGameStart();
	    
	    
	    loadGameResources();//加載遊戲資源
	    bfMapDraw();//畫背地圖,以後不用多次畫了
	    setFoods();
	    setSnake();
	    
	     Thread thread = new Thread(this); // 創建線程  
	     thread.start(); // 啓動線程  
	}
	
	//加載遊戲資源
	private void loadGameResources() {
	    try {
			imgDisplayInformation = ImageIO.read(new FileInputStream("images\\DisplayInformation.png"));
			imeGameOver = ImageIO.read(new FileInputStream("images\\GameOver.png"));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	//設置蛇
	private void setSnake() {
		snake=new Snake(Tools.MAP_X/2, Tools.MAP_Y/2, 0,rand.nextInt(Tools.SNAKE_STYLE_SUM));
		
//		int sx=rand.nextInt(Tools.MAP_X-40)+20;
//		int sy=rand.nextInt(Tools.MAP_Y-40)+20;
//		int sd=rand.nextInt(360);
//		int ss=rand.nextInt(Tools.SNAKE_STYLE_SUM);
//
//		enemy=new Snake(sx, sy, sd, ss);
	}

	// 設置食物
	private void setFoods() {

		foods=new Foods[Tools.FOODS_SUM];
		for(int i=0;i<Tools.FOODS_SUM;i++){

				int imgID=rand.nextInt(Tools.FOODS_TYPE_SUM);
				int drawX=rand.nextInt(Tools.MAP_X-40)+20;
				int drawY=rand.nextInt(Tools.MAP_Y-40)+20;
				//-------------可設計從XML文件讀入
				int generateEnergy;
				if (imgID<7){
					generateEnergy=1;
				}else {
					generateEnergy=5;
				}
				foods[i]=new Foods(imgID, drawX, drawY, generateEnergy);
		}

	}
	// 設置遊戲地圖
	private void bfMapDraw() {
		Graphics bfMapGraphics =bfMap.getGraphics();// 獲取緩衝圖片的畫筆
		
		bfMapGraphics.setColor(Color.BLACK); // 設置map外框爲黑色
		bfMapGraphics.fillRect(0, 0, Tools.MAP_X, Tools.MAP_Y);

		bfMapGraphics.setColor(new Color(90, 90, 90)); // 設置map牆爲黑色
		bfMapGraphics.fillRect(10, 10, Tools.MAP_X - 20, Tools.MAP_Y - 20);

		bfMapGraphics.setColor(new Color(208, 208, 224)); // 設置map背景色
		bfMapGraphics.fillRect(20, 20, Tools.MAP_X - 40, Tools.MAP_Y - 40);
		// 畫map格
		bfMapGraphics.setColor(new Color(241, 241, 240));
		for (int i = 20; i < Tools.MAP_Y; i += 20) {
			bfMapGraphics.drawLine(0 + 12, i, Tools.MAP_X -12, i);
		}

		for (int j = 20; j < Tools.MAP_X; j += 20) {
			bfMapGraphics.drawLine(j, 0 + 12, j, Tools.MAP_Y - 12);
		}
	}
	
	public void reDrawGame(){
		
		//得到畫地圖的偏移值
		drawMapX=-snake.getSnakeHeadX()+Tools.SCREEN_X/2;
		drawMapY=-snake.getSnakeHeadY()+Tools.SCREEN_Y/2;
		
		//畫地圖背景
		bfGameMapGraphics.setColor(Color.red);
		bfGameMapGraphics.fillRect(0, 0, Tools.SCREEN_X, Tools.SCREEN_Y);
		
		bfGameMapGraphics.drawImage(bfMap, drawMapX, drawMapY, null);//顯示第一層背景地圖
		
		for(int i=0;i<Tools.FOODS_SUM;i++){

			int distance = (int) Math.sqrt(Math.abs((foods[i].getDrawX() -  snake.getSnakeHeadX())*(foods[i].getDrawX() -  snake.getSnakeHeadX()))+Math.abs((foods[i].getDrawY() -  snake.getSnakeHeadY())*(foods[i].getDrawY() -  snake.getSnakeHeadY())));
			
			if (distance<25){//如果貪喫蛇離食物有20,測喫掉食物
				
				snake.setEnergy(snake.getEnergy()+foods[i].getGenerateEnergy());//能量加
				
				//產生新的食物

				foods[i].setDrawX(rand.nextInt(Tools.MAP_X-40)+20);
				foods[i].setDrawY(rand.nextInt(Tools.MAP_Y-40)+20);
			}
			foods[i].drawFoods(bfGameMapGraphics, drawMapX,drawMapY);

	}
		//===============================================
		if (snake.getSnakIsDeath()){//如果蛇在活着
			//snake.snakeMove();//蛇移動
			snake.snakeAutoMove();
			
			//判斷蛇是否撞牆
			if(snake.getSnakeHeadX()<=20||snake.getSnakeHeadX()>=(Tools.MAP_X-20)||snake.getSnakeHeadY()<=20||snake.getSnakeHeadY()>=(Tools.MAP_Y-20)){
				snake.snakeDeath();//蛇死亡了
				runGame=2;//遊戲結束
			}
		}

		snake.snakeShow(bfGameMapGraphics,drawMapX,drawMapY);

	}
	


	public void paint(Graphics gr) {
		switch (runGame){
		case 0:
			uiGameStart.drawUIGameStart(bfGameMapGraphics);
			gr.drawImage(bfGameMap,0,0, null); // 將緩衝map
			break;
		case 1:
			reDrawGame();
			//顯示得分
			showDisplayInformation();
			gr.drawImage(bfGameMap,0,0, null); // 將緩衝map
			
            break;
		case 2:
			reDrawGame();

			showDisplayInformation();
			bfGameMapGraphics.drawImage(imeGameOver,250,100, null);
			
			gr.drawImage(bfGameMap,0,0, null); // 將緩衝map
			break;
			
		default:
			break;
			
		}

 }  


		//顯示得分
		private void showDisplayInformation() {
			bfGameMapGraphics.drawImage(imgDisplayInformation,300,30, null); 
			bfGameMapGraphics.setColor(Color.RED);
			bfGameMapGraphics.setFont(new Font("arial",Font.BOLD, 30));
			bfGameMapGraphics.drawString(snake.getSnakeLength()+"", 460, 66);
			bfGameMapGraphics.drawString(snake.getEnergy()+"", 680, 66);
	}

		/** 
	     * 線程執行方法 
	     */  
	    public void run() {  
	        try {  
	            while (true) {  
	                this.repaint();  
	                Thread.sleep(inputSleep);  
	            }  
	        } catch (InterruptedException e) {  
	            e.printStackTrace();  
	        }  
	    }  
	  
	    /** 
	     * 按下時調用 
	     */  
	    public void keyPressed(KeyEvent e) {  
	    	
	        int keyCode = e.getKeyCode();
	        
	        //	遊戲剛啓動時,按任意鍵開始遊戲        
	        if (runGame==0){
	    		runGame=1;
	    	}
	        
	        if (keyCode ==KeyEvent.VK_LEFT&&runGame==1) { // 左按鍵  
	        	snake.setSnakeHeadDirection(snake.getSnakeHeadDirection()-5);//蛇左轉
	        }  
	        if (keyCode == KeyEvent.VK_RIGHT&&runGame==1) { // 右按鍵  
	        	snake.setSnakeHeadDirection(snake.getSnakeHeadDirection()+5);//蛇右轉
	        }  
	       if(keyCode==KeyEvent.VK_UP&&runGame==1){//加速
	    	   inputSleep=20;
	       }
	       if(keyCode==KeyEvent.VK_L&&runGame==2){//復活

	    	   snake.setSnakeHeadX(Tools.MAP_X/2);
	    	   snake.setSnakeHeadY(Tools.MAP_Y/2);
	    	   runGame=1;
	    	   snake.setSnakeIsDeath(true);
	       }
	       if(keyCode==KeyEvent.VK_Y&&runGame==2){//重新開始
	    	   snake.setSnakeHeadX(Tools.MAP_X/2);
	    	   snake.setSnakeHeadY(Tools.MAP_Y/2);
	    	   snake.setSnakeLength(3);
	    	   snake.setEnergy(0);
	    	   runGame=1;
	    	   snake.setSnakeIsDeath(true);
	       }
	    }  
	  
	    /** 
	     * 釋放按鍵時調用 
	     */  
	    public void keyReleased(KeyEvent e) {  
	    	 int keyCode = e.getKeyCode(); 
	    	 if(keyCode==KeyEvent.VK_UP){
		    	   inputSleep=80;
		       }
	    }  
	  
	    /** 
	     * 不解釋 
	     */  
	    public void keyTyped(KeyEvent e) {  
	  
	    }  
	  
	    public static void main(String[] args) {  
	        new SnakePlayer();  
	    }

	}


4、Tools.java

package com.hawkonline.retorsnaker;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

public class Tools {
	public static final int MAP_X = 1920;
	public static final int MAP_Y = 1080;
	public static final int SCREEN_X = 800;
	public static final int SCREEN_Y = 600;
	public static final String GameName = "美卡貪喫蛇1.0.0";

	public final static int FOODS_TYPE_SUM = 19;// 食物種類
	public final static int FOODS_SUM = 50;// 小圓食物總數
	public final static int SNAKE_STYLE_SUM = 6;// 蛇皮膚總數
	public final static int SNAKE__SUM=10;//蛇的數量
	
	/**
	 * 旋轉圖片爲指定角度
	 * 
	 * @param bufferedimage
	 *            目標圖像
	 * @param degree
	 *            旋轉角度
	 * @return
	 */
	public final static BufferedImage rotateImage(final BufferedImage bufferedimage, final int degree) {
		int w = bufferedimage.getWidth();// 得到圖片寬度。
		int h = bufferedimage.getHeight();// 得到圖片高度。
		int type = bufferedimage.getColorModel().getTransparency();// 得到圖片透明度。
		BufferedImage img;// 空的圖片。
		Graphics2D graphics2d;// 空的畫筆。
		(graphics2d = (img = new BufferedImage(w, h, type)).createGraphics())
				.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);// 旋轉,degree是整型,度數,比如垂直90度。
		graphics2d.drawImage(bufferedimage, 0, 0, null);// 從bufferedimagecopy圖片至img,0,0是img的座標。
		graphics2d.dispose();
		return img;// 返回複製好的圖片,原圖片依然沒有變,沒有旋轉,下次還可以使用。
	}

}

5、UIGameStart.java

package com.hawkonline.retorsnaker;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.imageio.ImageIO;


public class UIGameStart {

	private BufferedImage gameStart=null;
    private BufferedImage snakeImage=null;
    private BufferedImage snakeTxt=null;
    private BufferedImage imgRotate;// 旋轉後的圖片
    private int retate=0;
    private boolean left=true;
    
    public UIGameStart() {
    	try {
    		gameStart = ImageIO.read(new FileInputStream("images\\gameStart.png"));
    		snakeImage = ImageIO.read(new FileInputStream("images\\snakeImage.png"));
    		snakeTxt = ImageIO.read(new FileInputStream("images\\snakeTxt.png"));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
   
	}
    public void drawUIGameStart(Graphics cg){
    	cg.setColor(Color.BLACK);
    	cg.fillRect(0, 0, Tools.SCREEN_X, Tools.SCREEN_Y);
    	//畫背景
    	cg.drawImage(gameStart,0, 0, Tools.SCREEN_X, Tools.SCREEN_Y,null);
    	
    	//蛇頭動畫參數
    	if (left){
    		retate+=2;
    		if (retate==20) left=false;
    		
    	}else{
    		retate-=2;
    		if (retate==-20) left=true;
    	}
    	
    	imgRotate = Tools.rotateImage(snakeImage, retate);
    	
    	//居中顯示
    	cg.drawImage(imgRotate, (Tools.SCREEN_X-snakeImage.getWidth())/2, (Tools.SCREEN_Y-snakeImage.getHeight())/2, null);
    	cg.drawImage(snakeTxt, (Tools.SCREEN_X-snakeTxt.getWidth())/2, (Tools.SCREEN_Y-snakeTxt.getHeight())/2, null);
    	
    	cg.setColor(Color.RED);
    	cg.setFont(new Font("arial",Font.BOLD, 30));	
    }
}

直接運行。完工!!

snake.snakeAutoMove()是自動行走模式,實現了簡單的AI智能,經測試蛇在地圖上可以長時間不撞牆死掉。

如果改爲snake.snakeMove()是手動操控模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章