基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)

一.前言某日,看见隔壁家的小朋友在玩一款网络爆款贪吃蛇游戏,感觉很好玩。自己刚好正在学习JAVA编程,也想实现一个类似功能的游戏Demo练手,在网上查看了不少源码案例,全都是很古老的方块式贪吃蛇游戏案例,没有想要的实现,因此自己动手实现一个JAVA版的贪吃蛇游戏。我在这个Dome完成之后重写了这个游戏的Android版,并重新更名为《蛇王传说》。也欢迎大家下载试玩。游戏下载地址:https…

大家好,又见面了,我是你们的朋友全栈君。

一.前言

某日,看见隔壁家的小朋友在玩一款网络爆款贪吃蛇游戏,感觉很好玩。自己刚好正在学习JAVA编程,也想实现一个类似功能的游戏Demo练手,在网上查看了不少源码案例,全都是很古老的方块式贪吃蛇游戏案例,没有想要的实现,因此自己动手实现一个JAVA版的贪吃蛇游戏。

我在这个Dome完成之后重写了这个游戏的Android版,并重新更名为《蛇王传说》。也欢迎大家下载试玩。游戏下载地址:蒲公英 – 用户登录

我的另一篇博客有Androd版本的游戏介绍:蛇王传说1.0Android版发布_hawkol的专栏-CSDN博客基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)https://blog.csdn.net/hawkol/article/details/90608813

二、实现效果

1.启动界面 蛇头会左右摆动,动态效果

1

2、游戏主界面   地图上有不同的食物,用键盘控制蛇在地图上行走,每吃掉一个食物,蛇会自动生长一节

2

三、按键功能说明  左右键蛇转向,上键蛇加速行走。

基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)

四、美工准备

因自己不会美工,很多图都是从网上找的,然后用photoshop抠图,按自己的设计思路,做成以下样式。做片做的比较丑,就不放原图了。

1、images 文件夹

3

2、foolds文件夹

4

3、snake文件夹

5

4、在s0,s1,s2,s3,s4文件夹分别放以下5张图,可以做成不同颜色和样式(也就是蛇的皮肤)

基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)

五、打开Eclipse新建HawkRetroSnaker 项目,目录文件结构如下图:

从目录结构可以看出,此游戏有5个JAVA类,分别是

Foods.java (食物),

Snake.java (蛇),

SnakePlayer.java (游戏主程),

Tools.java (工具类),

UIGameStart.java (启动时的Ui).

基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)

六、游戏代码:关键代码地方都有注释,我就不多啰嗦了,代码写的比较烂,只是为了实现功能,有很多地方可以优化,大家也可提出自己的见解。

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()是手动操控模式。

 企业网站/微信小程序/app定制开发请添加微信:Hawkonline

基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)

 最新小程序案例

基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)  基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)   基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)    基于java的贪吃蛇游戏的设计与实现(贪吃蛇安卓游戏源码)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/125553.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • fstream读写文件read_使用同一个fstream

    fstream读写文件read_使用同一个fstream1.fstream是什么?fstream是C++标准库中面向对象库的一个,用于操作流式文件。fstream本质上是一个class,提供file操作的各种方法。2.关系图basic_fstream是一个类模板,暂且不用深入理解它。我们关心的事,它前面继承的那一堆东西。fstream是basic_fstream<char>的一个模板类,也就说明,fstream也继承了一堆东西。我们再关心一下从ios_base基类,重点继承了什么?文件流的打开模式。3.实验3.1打开/创建文件

    2022年9月19日
    2
  • vlan的原理和作用_生态因子作用的基本原理

    vlan的原理和作用_生态因子作用的基本原理相关名词:VirtualLocalAreaNetwork—VLAN、VirtualPrivateNetwork—VPN、VirtualRedundancyProtocol—VRRP等。一。VLAN的作用1.把一个广播帧所能到达的整个范围称为二层广播域,简称广播域。显然,一个交换网络其实就是一个广播域。在该网络中,假定PC0向PC10发送一个单播帧Y…

    2022年8月10日
    5
  • 深入浅出Windows BATCH

    深入浅出Windows BATCH

    2021年12月13日
    51
  • c# mysql executenonquery_C#与数据库访问技术之ExecuteNonQuery方法

    c# mysql executenonquery_C#与数据库访问技术之ExecuteNonQuery方法ExecuteNonQuery方法主要用来更新数据。通常使用它来执行Update、Insert和Delete语句。该方法返回值意义如下:对于Update、Insert和Delete语句,返回值为该命令所影响的行数。对于所有其他类型的语句,返回值为-1。Command对象通过ExecuteNonQuery方法更新数据库的过程非常简单,需要进行的步骤如下:(1)创建数据库连接。(2)创建Command…

    2022年9月12日
    2
  • OllyDBG 入门

    OllyDBG 入门一 OllyDBG 的安装与配置 OllyDBG1 10 版的发布版本是个 ZIP 压缩包 只要解压到一个目录下 运行 OllyDBG exe 就可以了 汉化版的发布版本是个 RAR 压缩包 同样只需解压到一个目录下运行 OllyDBG exe 即可 OllyDBG 中各个窗口的功能如上图 简单解释一下各个窗口的功能 更详细的内容可以参考 TT 小组翻译的中文帮助 反汇编窗口 显示被调试程序的反汇编代码 标题栏上的地址 HEX 数据 反汇编 注释可以通过在窗口中右击出现的菜单界面选项 gt 隐藏

    2025年5月9日
    6
  • 镁光ssd管理工具 linux,SandForce主控固态硬盘SF-2241 vb2开卡成功经验「建议收藏」

    镁光ssd管理工具 linux,SandForce主控固态硬盘SF-2241 vb2开卡成功经验「建议收藏」一个威刚SP900128G固态硬盘坏了,想用开卡软件来修复,然后就必须知道是什么主控,于是拆开看里面SandForceSF2241VB2的主控芯片,flash看不懂600739095300463844,最后试出来是28044,MT29F128G08CFABBWP20MLCMicron镁光的。然后按量产网的SF2000开卡教程,开卡SandForce主控的ssd需要用到linux系统,于是…

    2022年6月22日
    102

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号