大家好,又见面了,我是你们的朋友全栈君。
一.前言
某日,看见隔壁家的小朋友在玩一款网络爆款贪吃蛇游戏,感觉很好玩。自己刚好正在学习JAVA编程,也想实现一个类似功能的游戏Demo练手,在网上查看了不少源码案例,全都是很古老的方块式贪吃蛇游戏案例,没有想要的实现,因此自己动手实现一个JAVA版的贪吃蛇游戏。
我在这个Dome完成之后重写了这个游戏的Android版,并重新更名为《蛇王传说》。也欢迎大家下载试玩。游戏下载地址:蒲公英 – 用户登录
我的另一篇博客有Androd版本的游戏介绍:蛇王传说1.0Android版发布_hawkol的专栏-CSDN博客https://blog.csdn.net/hawkol/article/details/90608813
二、实现效果
1.启动界面 蛇头会左右摆动,动态效果
2、游戏主界面 地图上有不同的食物,用键盘控制蛇在地图上行走,每吃掉一个食物,蛇会自动生长一节
三、按键功能说明 左右键蛇转向,上键蛇加速行走。
四、美工准备
因自己不会美工,很多图都是从网上找的,然后用photoshop抠图,按自己的设计思路,做成以下样式。做片做的比较丑,就不放原图了。
1、images 文件夹
2、foolds文件夹
3、snake文件夹
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()是手动操控模式。
企业网站/微信小程序/app定制开发请添加微信:Hawkonline
最新小程序案例
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/156294.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...