package snake;
import javax.swing.*;
import java.net.URL;
/**
* 存放蛇的数据
*/
public class Data {
private static URL bodyURL = Data.class.getResource("img/body.png");
private static URL downURL = Data.class.getResource("img/down.png");
private static URL foodURL = Data.class.getResource("img/food.png");
private static URL headerURL = Data.class.getResource("img/header.png");
private static URL leftURL = Data.class.getResource("img/left.png");
private static URL rightURL = Data.class.getResource("img/right.png");
private static URL upURL = Data.class.getResource("img/up.png");
private static ImageIcon bodyIMG = new ImageIcon(bodyURL);
private static ImageIcon downIMG = new ImageIcon(downURL);
private static ImageIcon foodIMG = new ImageIcon(foodURL);
private static ImageIcon headerIMG = new ImageIcon(headerURL);
private static ImageIcon leftIMG = new ImageIcon(leftURL);
private static ImageIcon rightIMG = new ImageIcon(rightURL);
private static ImageIcon upIMG = new ImageIcon(upURL);
public static ImageIcon getBodyIMG() {
return bodyIMG;
}
public static void setBodyIMG(ImageIcon bodyIMG) {
Data.bodyIMG = bodyIMG;
}
public static ImageIcon getDownIMG() {
return downIMG;
}
public static void setDownIMG(ImageIcon downIMG) {
Data.downIMG = downIMG;
}
public static ImageIcon getFoodIMG() {
return foodIMG;
}
public static void setFoodIMG(ImageIcon foodIMG) {
Data.foodIMG = foodIMG;
}
public static ImageIcon getHeaderIMG() {
return headerIMG;
}
public static void setHeaderIMG(ImageIcon headerIMG) {
Data.headerIMG = headerIMG;
}
public static ImageIcon getLeftIMG() {
return leftIMG;
}
public static void setLeftIMG(ImageIcon leftIMG) {
Data.leftIMG = leftIMG;
}
public static ImageIcon getRightIMG() {
return rightIMG;
}
public static void setRightIMG(ImageIcon rightIMG) {
Data.rightIMG = rightIMG;
}
public static ImageIcon getUpIMG() {
return upIMG;
}
public static void setUpIMG(ImageIcon upIMG) {
Data.upIMG = upIMG;
}
}
package snake;
import javax.swing.*;
/**
* 游戏主启动类
*/
public class StartGame {
public static void main(String[] args) {
/*
窗口基本设置
*/
JFrame jFrame = new JFrame("贪吃蛇小游戏");
//固定窗口大小
jFrame.setResizable(false);
/*
面板:一定要放在setVisible(true)的前面;
因为获得的焦点事件setFocusable(true)和键盘的监听事件addKeyListener(this)
一定要放在setVisible(true)的前面;
否则会导致键盘监听失效
*/
jFrame.add(new GamePanel());
//设置窗口可见性
jFrame.setVisible(true);
//设置窗口定位和大小
jFrame.setBounds(10,10,900,720);
//设置关闭窗口监听
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
package snake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
/**
* 游戏的面板
*/
public class GamePanel extends JPanel implements KeyListener,ActionListener{
int length;// 蛇的长度
int[] snakeX = new int[500];// 蛇的X坐标
int[] snakeY = new int[500];// 蛇的Y坐标
// 食物的坐标
int foodx;
int foody;
// 随机数
Random random = new Random();
String direction;// 小蛇头的方向
boolean isStart = false;// 游戏初始状态为停止
boolean isFail = false;// 游戏失败状态
int score;// 游戏得分
/*
定时器:每隔100毫秒执行一次实现的ActionListener接口中的actionPerformed的方法体
*/
Timer timer = new Timer(100,this);
// 启动
public GamePanel(){
//初始化蛇
init();
//获得焦点事件
this.setFocusable(true);
//获得键盘的监听事件
this.addKeyListener(this);
// 开启定时器
timer.start();
}
/*
初始化蛇
*/
public void init(){
/*
每个方块图形大小:25*25
X坐标依次减25便于蛇身排列在一行
*/
length = 3;// 初始时蛇只有三个块
snakeX[0] = 100;snakeY[0] = 100;// 初始时蛇第一个块的坐标(蛇头)
snakeX[1] = 75;snakeY[1] = 100;// 初始时蛇第二个块的坐标
snakeX[2] = 50;snakeY[2] = 100;// 初始时蛇第三个块的坐标
direction = "R";// 小蛇头初始方向为右
// 把食物随机分布在游戏界面上
foodx = 25+random.nextInt(34)*25;//850除25=34
foody = 75+random.nextInt(24)*25;//600除25=24
score = 0;// 游戏得分
}
/*
画笔
*/
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景颜色
this.setBackground(Color.WHITE);
// 广告栏界面
//Data.getHeaderIMG().paintIcon(this,g,250,11);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("广告位招租",320,50);
//动态绘制游戏得分
g.setColor(Color.BLUE);
g.setFont(new Font("微软雅黑",Font.BOLD,20));
g.drawString("当前长度:"+length,750,25);
g.drawString("当前得分:"+score,750,50);
// 绘制矩形游戏界面
g.setColor(Color.BLACK);
g.fillRect(25,75,850,600);
// 动态绘制小蛇头的方向
if (direction.equals("R")){
Data.getRightIMG().paintIcon(this,g,snakeX[0],snakeY[0]);
}else if (direction.equals("L")){
Data.getLeftIMG().paintIcon(this,g,snakeX[0],snakeY[0]);
}else if (direction.equals("U")){
Data.getUpIMG().paintIcon(this,g,snakeX[0],snakeY[0]);
}else if (direction.equals("D")){
Data.getDownIMG().paintIcon(this,g,snakeX[0],snakeY[0]);
}else {
System.out.println("错误:未知的方向!");
}
// 动态绘制小蛇身体
for (int i = 1; i < length; i++) {
Data.getBodyIMG().paintIcon(this,g,snakeX[i],snakeY[i]);
}
//动态绘制食物
Data.getFoodIMG().paintIcon(this,g,foodx,foody);
/*
游戏状态
*/
if (isStart==false){
g.setColor(Color.WHITE);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("按下空格开始游戏",300,300);
}
/*
游戏失败
*/
if (isFail){
g.setColor(Color.RED);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("游戏失败!按下空格重新开始!",300,300);
g.setColor(Color.BLUE);
g.drawString("当前得分:"+score,300,350);
}
}
// 键盘监听
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
// 如果按下空格
if (keyCode == KeyEvent.VK_SPACE){
if (isFail){
/*
游戏重新开始
*/
isFail = false;
// 重新开始小蛇的初始位置
init();
}else {
// 取反,这样空格才能开始和停止游戏,不能写死
isStart = !isStart;
}
// isStart值已经发生变化,需要重新加载画笔paintComponent(Graphics g)方法
repaint();
}
/*
游戏开始后键盘才能控制小蛇头上下左右动
*/
if (isStart){
if (keyCode == KeyEvent.VK_UP){
direction = "U";
}else if (keyCode == KeyEvent.VK_DOWN){
direction = "D";
}else if (keyCode == KeyEvent.VK_LEFT){
direction = "L";
}else if (keyCode == KeyEvent.VK_RIGHT){
direction = "R";
}
// direction值已经发生改变,需要重新加载画笔paintComponent(Graphics g)方法
repaint();
}
}
// 定时器事件监听
@Override
public void actionPerformed(ActionEvent e) {
/*
游戏开始状态
*/
if (isStart && isFail == false){
// 小蛇头direction默认等于R
// 小蛇身体移动
for (int i = length-1;i>0;i--){
snakeX[i] = snakeX[i-1];
snakeY[i] = snakeY[i-1];
}
if (direction.equals("U")){
// 小蛇头上移
snakeY[0] = snakeY[0]-25;
// 上边界判断
if (snakeY[0]<75){
snakeY[0]=600;
}
}else if(direction.equals("D")){
// 小蛇头下移
snakeY[0] = snakeY[0]+25;
// 下边界判断
if (snakeY[0]>650){
snakeY[0]=75;
}
}else if (direction.equals("L")){
// 小蛇头左移
snakeX[0] = snakeX[0]-25;
// 左边界判断
if (snakeX[0]<25){
snakeX[0]=850;
}
}else if (direction.equals("R")){
// 小蛇头右移
snakeX[0] = snakeX[0]+25;
// 右边界判断
if (snakeX[0]>850){
snakeX[0]=25;
}
}
/*
小蛇吃食物:蛇头的坐标等于食物的坐标
*/
if (snakeX[0]==foodx&&snakeY[0]==foody){
length++;// 蛇身长度加1
score+=10;// 分数加10
/*
食物再次出现:把食物随机分布在游戏界面上
*/
foodx = 25+random.nextInt(34)*25;//850除25=34
foody = 75+random.nextInt(24)*25;//600除25=24
}
/*
判断游戏失败:蛇头撞到自己的身体就算失败
*/
for (int i = 1; i < length; i++) {
if (snakeX[0]==snakeX[i]&&snakeY[0]==snakeY[i]){
isFail = true;// 游戏失败
}
}
/*
判断游戏失败:蛇头撞到上下左右边界就算失败
*/
// if (snakeX[0]==875||snakeX[0]==0||snakeY[0]==675||snakeY[0]==0){
// isFail = true;// 游戏失败
// snakeX[0] = 875;
// }
//蛇的参数改变了,需要重新加载画笔
repaint();
}
// 开启定时器
timer.start();
}
/*
无用的两个键盘监听方法
*/
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
注:仅供学习参考,非商用。侵权私信本人删除。
参考资料:
https://www.bilibili.com/video/BV1DJ411B75F?p=26