贪吃蛇能够被键盘wasd控制移动,小蛇每吃到一个食物,分数加1,撞到自己,则显示游戏结束。游戏可以被space键暂停继续。
在600*600像素的方框中(蛇的主要移动范围),定义蛇移动一次以30*30的像素移动。
public class GameWin extends JFrame { public void init(){ this.setVisible(true); this.setSize(600,600); this.setLocationRelativeTo(null); this.setTitle("贪吃蛇小游戏"); } public static void main(String[] args) { GameWin gameWin = new GameWin(); gameWin.init(); } }
import java.awt.*; public class GameObj { Image img; int x; int y; int width = 30; int height = 30; GameWin frame; public Image getImg() { return img; } public void setImg(Image img) { this.img = img; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public GameWin getFrame() { return frame; } public void setFrame(GameWin frame) { this.frame = frame; } public GameObj() { } public GameObj(Image img, int x, int y,GameWin frame) { this.img = img; this.x = x; this.y = y; this.frame = frame; } public void paintSelf(Graphics g){ g.drawImage(img,x,y,null); } }
import java.awt.*; public class GameUtils { public static Image headImage = Toolkit.getDefaultToolkit().getImage("img/head.png"); public static Image bodyImage = Toolkit.getDefaultToolkit().getImage("img/body.png"); public static Image foodImage = Toolkit.getDefaultToolkit().getImage("img/food.png"); public static void drawWord(Graphics g,String str,Color color,int size,int x,int y){ g.setColor(color); g.setFont(new Font("仿宋",Font.BOLD,size)); g.drawString(str,x,y); } }
import java.awt.*; public class HeadObj extends GameObj { private String direction = "right"; public String getDirection() { return direction; } public void setDirection(String direction) { this.direction = direction; } public HeadObj(Image img, int x, int y, GameWin frame) { super(img, x, y, frame); } @Override public void paintSelf(Graphics g) { super.paintSelf(g); } }
public void changeDirection(KeyEvent e){ switch(e.getKeyCode()){ case KeyEvent.VK_A: if(!direction.equals("right")){ direction = "left"; } break; case KeyEvent.VK_D: if(!direction.equals("left")){ direction = "right"; } break; case KeyEvent.VK_W: if(!direction.equals("down")){ direction = "up"; } break; case KeyEvent.VK_S: if(!direction.equals("up")){ direction = "down"; } break; default: break; }
import java.awt.*; public class BodyObj extends GameObj { public BodyObj(Image img, int x, int y, GameWin frame) { super(img, x, y, frame); } @Override public void paintSelf(Graphics g) { super.paintSelf(g); } }
import java.awt.*; import java.util.Random; public class FoodObj extends GameObj { Random r = new Random(); public FoodObj() { super(); } public FoodObj getFood(){ return new FoodObj(GameUtils.foodImage,r.nextInt(20)*30,( r.nextInt(19)+1)*30,this.frame ); } public FoodObj(Image img, int x, int y, GameWin frame) { super(img, x, y, frame); } @Override public void paintSelf(Graphics g) { super.paintSelf(g); } }
有利于工程开发思维的培养,稳固知识点,增强团队分工合作的意识。 意识到了自己知识水平还有很大缺陷,和高手之间还有很长的路要走。
1,界面字有闪烁问题:双缓存解决 游戏单调问题:增加关卡设置,增加障碍物,增加通关界面 游戏运行效率不高:改进小蛇移动时候,贴图的移动方法,可以只改变蛇头和蛇尾使小蛇移动,增加多线程的应用 2,进一步学习Java高级开发工具类,学习多线程,学习网络开发, docker容器,学习一些开发web技术
package com.draw.test01; import javax.swing.*; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; public class GameWin extends JFrame { //继承了Jframe类便具有了创建窗口,监听鼠标键盘事件的功能 //记录分数 public static int score = 0; //游戏状态 0未开始 1游戏中 2暂停 3失败 4通关 public static int state = 0; int winWidth = 800; int winHeight = 600; //蛇的头部 HeadObj headObj = new HeadObj(GameUtils.rightImg,30,30,this);//窗口引用是当前对象this //蛇身体的集合 public List<BodyObj> bodyObjList = new ArrayList<BodyObj>(); //food public FoodObj foodObj = new FoodObj().getFood(); public void init(){ //设置窗口是否可见 this.setVisible(true); //设置窗口大小 this.setSize(winWidth,winHeight); //设置窗口标题 this.setTitle("贪吃蛇小游戏"); //蛇身体的初始化 bodyObjList.add(new BodyObj(GameUtils.bodyImg,30,570,this)); bodyObjList.add(new BodyObj(GameUtils.bodyImg,0,570,this)); //添加键盘事件 this.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_SPACE){ switch(state){ case 0: case 2: state =1; break; case 1: state = 2; repaint(); break; default: break; } } } }); while(true){ if(state == 1){ repaint(); } try { Thread.sleep(200);//每次重绘过后,线程休眠,1秒刷新5次 }catch(InterruptedException e){ e.printStackTrace(); } } } //重写paint方法 @Override public void paint(Graphics g) { //super.paint(g); //灰色背景 g.setColor(Color.GRAY); //填充矩形 g.fillRect(0,0,winWidth,winHeight); //网格线 g.setColor(Color.LIGHT_GRAY); //for(int i=1;i<=20;i++){ g.drawLine(600,30,600,600); // g.drawLine(30*i,0,30*i,600); //} //反向遍历身体的集合,防止想要的数据被覆盖 for (int i = bodyObjList.size()-1; i >= 0 ; i--) { bodyObjList.get(i).paintSelf(g); } //在paint 方法中绘制蛇头 headObj.paintSelf(g); //食物的绘制 foodObj.paintSelf(g); //将分数绘制出来 GameUtils.drawWord(g,score+" 分",Color.BLUE,50,650,300); g.setColor(Color.GRAY); prompt(g); } //绘制提示语 void prompt(Graphics g){ if(state == 0){ g.fillRect(120,240,400,70); GameUtils.drawWord(g,"按下空格开始游戏",Color.yellow,35,150,290); } if(state == 2){ g.fillRect(120,240,400,70); GameUtils.drawWord(g,"按下空格继续游戏",Color.BLUE,35,150,290); } if(state == 3){ g.fillRect(120,240,400,70); GameUtils.drawWord(g,"回家种地去吧",Color.RED,35,150,290); } } public static void main(String[] args) { GameWin gamewin = new GameWin(); gamewin.init(); } }
package com.draw.test01; import java.awt.*; //游戏的工具类 public class GameUtils { //蛇头 //public static Image upImg = Toolkit.getDefaultToolkit().getImage("img/test.png"); //public static Image dowmImg = Toolkit.getDefaultToolkit().getImage("img/test.png"); //public static Image leftImg = Toolkit.getDefaultToolkit().getImage("img/test.png"); public static Image rightImg = Toolkit.getDefaultToolkit().getImage("img/test.png"); //蛇身 public static Image bodyImg = Toolkit.getDefaultToolkit().getImage("img/body.png"); //蛇的食物 public static Image foodImg = Toolkit.getDefaultToolkit().getImage("img/food.png"); public static void drawWord(Graphics g,String str,Color color,int size,int x,int y){ g.setColor(color); g.setFont(new Font("仿宋",Font.BOLD,size)); g.drawString(str, x, y); } }
package com.draw.test01; import java.awt.*; //创建游戏物体的父类 public class GameObj { //picture Image img; //coordinate int x; int y; int width = 30; int height = 30; //窗口类的引用 GameWin frame ; public Image getImg() { return img; } public void setImg(Image img) { this.img = img; } public int getX() { return x; } public GameObj(Image img, int x, int y, GameWin frame) { this.img = img; this.x = x; this.y = y; this.frame = frame; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public GameWin getFrame() { return frame; } public void setFrame(GameWin frame) { this.frame = frame; } //无参构造 public GameObj() { } //有参构造 public GameObj(Image img, int x, int y, int width, int height, GameWin frame) { this.img = img; this.x = x; this.y = y; this.width = width; this.height = height; this.frame = frame; } //绘制自身 public void paintSelf(Graphics g){ g.drawImage(img,x,y,null); } }
package com.draw.test01; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.List; //蛇的头部 public class HeadObj extends GameObj{ //方向 up down left right private String direction = "right"; public HeadObj(Image img, int x, int y, GameWin frame) { super(img, x, y, frame); //在构造方法中添加键盘监听事件 this.frame.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { //super.keyPressed(e);//键盘按下、、获取到了键盘事件e changeDirection(e); } }); } //控制移动方向 public void changeDirection(KeyEvent e){ switch(e.getKeyCode()){ case KeyEvent.VK_A: if(!direction.equals("right")){ direction = "left"; } break; case KeyEvent.VK_D: if(!direction.equals("left")){ direction = "right"; } break; case KeyEvent.VK_S: if(!direction.equals("up")){ direction = "down"; } break; case KeyEvent.VK_W: if(!direction.equals("down")){ direction = "up"; } break; default: break; } } public String getDirection() { return direction; } public void setDirection(String direction) { this.direction = direction; } public void move (){ //在蛇头移动之前先把蛇身移动 List<BodyObj> bodyObjList = this.frame.bodyObjList; for (int i = bodyObjList.size() - 1; i >= 1; i--) { bodyObjList.get(i).x = bodyObjList.get(i-1).x; bodyObjList.get(i).y = bodyObjList.get(i-1).y; if(this.x == bodyObjList.get(i).x&&this.y == bodyObjList.get(i).y){ GameWin.state = 3; } } bodyObjList.get(0).x = this.x; bodyObjList.get(0).y = this.y; switch(direction){ case "up": y -= height; break; case "down": y += height; break; case "left": x -= width; break; case "right": x += width; break; } } @Override public void paintSelf(Graphics g) { super.paintSelf(g); //获取窗口类中的食物对象,蛇吃食物 FoodObj food = this.frame.foodObj; //身体最后一节的坐标 Integer X = null; Integer Y = null; if(food.x == this.x&&food.y== this.y){ //获取蛇最后一节的坐标 BodyObj lastBody = this.frame.bodyObjList.get(this.frame.bodyObjList.size()-1); X = lastBody.x; Y = lastBody.y; //蛇每吃一个食物,分数加一 GameWin.score++; this.frame.foodObj = food.getFood(); } move(); if(X != null && Y != null){ this.frame.bodyObjList.add(new BodyObj(GameUtils.bodyImg,X,Y,this.frame)); } //越界处理 if(x<0){ x = 570; } else if(x>570){ x = 0; } else if(y<30){ y = 570; } else if(y>570){ y = 30; } } }
package com.draw.test01; import java.awt.*; public class BodyObj extends GameObj{ public BodyObj(Image img, int x, int y, GameWin frame) { super(img, x, y, frame); } @Override public void paintSelf(Graphics g) { super.paintSelf(g); } }
package com.draw.test01; import java.awt.*; import java.util.Random; public class FoodObj extends GameObj{ //定义随机函数 Random random = new Random(); public FoodObj() { super(); } public FoodObj(Image img, int x, int y, GameWin frame) { super(img, x, y, frame); } //获取食物 public FoodObj getFood(){ return new FoodObj(GameUtils.foodImg,random.nextInt(20)*30,(random.nextInt(19)+1)*30,this.frame); } @Override public void paintSelf(Graphics g) { super.paintSelf(g); } }