图片导入:
package main.test;
import javax.swing.*;
import java.net.URL;
public class Images {
//蛇头图片的URL(路径)封装成为一个对象
public static URL headUrl = Images.class.getResource("/main/images/head.png");
//将蛇头图片URL的对象封装成为蛇头图片对象
public static ImageIcon head = new ImageIcon(headUrl);
//蛇身图片的URL(路径)封装成为一个对象
public static URL bodyUrl = Images.class.getResource("/main/images/board.png");
//将蛇身图片URL的对象封装成为蛇身图片对象
public static ImageIcon body = new ImageIcon(bodyUrl);
//食物图片的URL(路径)封装成为一个对象
public static URL foodUrl = Images.class.getResource("/main/images/food.png");
//将食物图片URL的对象封装成为食物图片对象
public static ImageIcon food = new ImageIcon(foodUrl);
}
URL测试:
package main.test;
import java.net.URL;
//URL路径测试文件
public class UrlTest {
public static void main(String[] args) {
URL url = Images.class.getResource("/");
System.out.println(url);
}
}
主类:
package main.test;
import javax.swing.*;
import java.awt.*;
public class StartGame {
public static void main(String[] args) {
//创建窗体
JFrame jf = new JFrame();
//设置窗口标题
jf.setTitle("贪吃蛇");
//设置窗体大小和位置
//获取电脑屏幕的宽高
int x = Toolkit.getDefaultToolkit().getScreenSize().width;
int y = Toolkit.getDefaultToolkit().getScreenSize().height;
int width = 990, height = 700;
//设置(坐标x,坐标y,窗口width,窗口height)
jf.setBounds((x-width)/2,(y-height)/2,width,height);
//设置窗口大小不可变
jf.setResizable(false);
//设置窗口关闭同时关闭程序
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口面板
//创建面板对象
GamePanel gp = new GamePanel();
//将面板放入窗口
jf.add(gp);
//设置窗口显示
jf.setVisible(true);
}
}
面板类:
package main.test;
/*
*
* 界面类
*
* */
import javax.swing.*;
import java.awt.*;
public class GamePanel extends JPanel{
//创建蛇对象
Snake snake = new Snake();
//事件监听
SnakeMethod sm ;
//蛇体移动
SnakeDo sd;
//构造方法
public GamePanel(){
sm = new SnakeMethod(snake, this) ;
sd = new SnakeDo(snake, this);
//定时器启动
sd.timer.start();
}
//此方法可以说是图形窗口的main方法
@Override
protected void paintComponent(Graphics g) {//g是一个画笔
super.paintComponent(g);
//设置面板背景颜色
this.setBackground(new Color(120,170,120));
//窗体布局,上方留空(50px),做菜单栏
/*
* 菜单栏
* */
//画一个矩形框做游戏板
g.setColor(new Color(100,150,180));
g.fillRect(15,60,940,580);
//初始化蛇体图片 容器 工具 x坐标 y坐标
Images.head.paintIcon(this,g,snake.snakeX[0],snake.snakeY[0]);
/*
* 如果有多张蛇头图片(取决于身体运动方向而绘制不同图片)
*
* if(direction.equals("L"))
* Images.head_LEFT.paintIcon(this,g,snakeX[0],snakeY[0]);
* else if(direction.equals("U"))
* Images.head_UP.paintIcon(this,g,snakeX[0],snakeY[0]);
* else if(direction.equals("D"))
* Images.head_DOWN.paintIcon(this,g,snakeX[0],snakeY[0]);
* else if(direction.equals("R"))
* Images.head_RIGHT.paintIcon(this,g,snakeX[0],snakeY[0]);
*
* */
/*
Images.body.paintIcon(this,g,snakeX[1],snakeY[1]);
Images.body.paintIcon(this,g,snakeX[2],snakeY[2]);
*/
//优化蛇身绘制
for(int i = 1; i < snake.getLen(); i++){
Images.body.paintIcon(this,g,snake.snakeX[i],snake.snakeY[i]);
}
//打印食物
Images.food.paintIcon(this,g,snake.getFoodX(),snake.getFoodY());
//绘制积分
//设置字体
g.setFont(new Font("微软雅黑",Font.BOLD,28));
//设置颜色
g.setColor(new Color(196,80, 100));
//绘制文字提示
g.drawString("积分:" + snake.getScore(),830,40);
//暂停状态提示
if(!snake.isFalse()){
//设置字体
g.setFont(new Font("微软雅黑",Font.BOLD,58));
//设置颜色
g.setColor(new Color(236,120, 240));
//绘制文字提示
g.drawString("按下空格开始游戏",270,300);
}
//死亡提示
if(snake.isDie()){
//设置字体
g.setFont(new Font("微软雅黑",Font.BOLD,58));
//设置颜色
g.setColor(new Color(236,120, 240));
//绘制文字提示
g.drawString("你凉了,得分: " + snake.getScore() +",空格重开!",125,300);
}
//模式提示
//设置字体
g.setFont(new Font("微软雅黑",Font.BOLD,28));
//设置颜色
g.setColor(new Color(196,80, 100));
if(snake.getSpeed() == 100){
//绘制文字提示
g.drawString("中等",30,40);
}
else if(snake.getSpeed() == 70){
//绘制文字提示
g.drawString("简单",30,40);
}
else if(snake.getSpeed() == 130){
//绘制文字提示
g.drawString("困难",30,40);
}
}
}
蛇体移动类:
package main.test;
/*
* 蛇体移动类
* */
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class SnakeDo {
//创建定时器
Timer timer;
public SnakeDo(Snake snake, GamePanel gp){
//定时器
timer = new Timer(snake.getSpeed(), new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//如果游戏处于开始状态
if(snake.isFalse() && !snake.isDie()){
//移动蛇身到上一节蛇身的位置
for(int i = snake.getLen() - 1; i > 0; i--){
snake.snakeX[i] = snake.snakeX[i - 1];
snake.snakeY[i] = snake.snakeY[i - 1];
}
//移动蛇头
if(snake.getDirection().equals("R")){
snake.snakeX[0] += 20;//右移25格
}
if(snake.getDirection().equals("L")){
snake.snakeX[0] -= 20;//左移25格
}
if(snake.getDirection().equals("U")){
snake.snakeY[0] -= 20;//上移25格
}
if(snake.getDirection().equals("D")){
snake.snakeY[0] += 20;//下移25格
}
//如果蛇头超过范围则从另一端开始
if(snake.snakeX[0] > 935){
snake.snakeX[0] = 15;
}
if(snake.snakeX[0] < 15){
snake.snakeX[0] = 935;
}
if(snake.snakeY[0] > 620){
snake.snakeY[0] = 60;
}
if(snake.snakeY[0] < 60){
snake.snakeY[0] = 620;
}
//吃食物
if(snake.snakeX[0] == snake.getFoodX() && snake.snakeY[0] == snake.getFoodY()){
//蛇身+1
snake.setLen(snake.getLen() + 1);
//积分+10
snake.setScore(snake.getScore() + 10);
//食物不能在蛇的身体上
boolean flag = false;
while(!flag){
boolean fla = true;
Random r = new Random();
snake.setFoodX((r.nextInt(45) + 1) * 20 + 15);//[15, 955]之间的20的倍数
snake.setFoodY((r.nextInt(28) + 1) * 20 + 60);//[60, 640]之间的20的倍数
for(int i = 0; i < snake.getLen();i++){
if (snake.snakeX[i] == snake.getFoodX() && snake.snakeY[i] == snake.getFoodY()){
fla = false;
break;
}
}
if(fla){
flag = true;
}
}
}
//判断蛇是否死亡
for(int i = 1; i < snake.getLen(); i++){
if(snake.snakeX[0] == snake.snakeX[i] && snake.snakeY[0] == snake.snakeY[i]){
snake.setDie(true);
}
}
gp.repaint();//重绘,调用paintComponent(Graphics g)
}
}
});
}
}
事件监听类:
package main.test;
/*
* 事件监听类
* */
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class SnakeMethod{
public SnakeMethod(Snake snake, GamePanel gp){
//监听空格按键
//先定位焦点到窗口
gp.setFocusable(true);
//监听
gp.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int keyCode = e.getKeyCode();
//按下空格
if(keyCode == 32){
//存活状态下进行暂停或者重启
if(!snake.isDie()){
System.out.println(keyCode);
//状态取反
snake.setFalse(!snake.isFalse());
gp.repaint();//重绘,调用paintComponent(Graphics g)
}
//死亡状态下初始化游戏
else {
snake.setDie(!snake.isDie());
snake.init();
}
}
//监听上下左右,asdw
//按键方向与现在方向相同或者相反都不执行
if((keyCode == KeyEvent.VK_A || keyCode == KeyEvent.VK_LEFT)
&& !snake.getDirection().equals("R") && !snake.getDirection().equals("L") ){
snake.setDirection("L");
System.out.println(keyCode);
}
if((keyCode == KeyEvent.VK_D || keyCode == KeyEvent.VK_RIGHT)
&& !snake.getDirection().equals("R") && !snake.getDirection().equals("L") ){
snake.setDirection("R");
System.out.println(keyCode);
}
if((keyCode == KeyEvent.VK_W || keyCode == KeyEvent.VK_UP)
&& !snake.getDirection().equals("U") && !snake.getDirection().equals("D") ){
snake.setDirection("U");
System.out.println(keyCode);
}
if((keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN)
&& !snake.getDirection().equals("U") && !snake.getDirection().equals("D") ){
snake.setDirection("D");
System.out.println(keyCode);
}
}
});
}
}
蛇类:
package main.test;
/*
* 蛇类
*
* */
public class Snake {
//设置蛇的数据
//蛇的长度
private int len;
//蛇身的x坐标数组
public int[] snakeX = new int[800];
//蛇身的y坐标数组
public int[] snakeY = new int[800];
//蛇头方向
private String direction;
//游戏状态
private boolean isFalse = false;//初始为暂停
//食物坐标
private int foodX, foodY;
//积分
private int score;
//蛇移动速度
private int speed;
//蛇的生命状态
private boolean isDie = false;//默认存活
//游戏定时器
//Timer timer;
//初始化蛇的数据
public void init(){
//初始化 蛇头和两节蛇身
//原点是(15,60),步长是20 ,宽高是(940,580)
snakeX[0] = 315;
snakeY[0] = 340;
snakeX[1] = 295;
snakeY[1] = 340;
snakeX[2] = 275;
snakeY[2] = 340;
//初始化蛇的长度
len = 3;
//初始化蛇头方向
direction = "R";//右
//初始化食物坐标
foodX = 675;
foodY = 260;
//初始化积分
score = 0;
//初始化蛇的速度
speed = 100;
}
public Snake(){
init();
}
public int getFoodX() {
return foodX;
}
public int getFoodY() {
return foodY;
}
public int getScore() {
return score;
}
public int getLen() {
return len;
}
public int getSpeed() {
return speed;
}
public String getDirection() {
return direction;
}
public boolean isDie() {
return isDie;
}
public boolean isFalse() {
return isFalse;
}
public void setDie(boolean die) {
isDie = die;
}
public void setDirection(String direction) {
this.direction = direction;
}
public void setFalse(boolean aFalse) {
isFalse = aFalse;
}
public void setFoodX(int foodX) {
this.foodX = foodX;
}
public void setFoodY(int foodY) {
this.foodY = foodY;
}
public void setLen(int len) {
this.len = len;
}
public void setScore(int score) {
this.score = score;
}
public void setSpeed(int speed) {
this.speed = speed;
}
}
本程序借鉴自:【B站最好|Java实战项目】马士兵Java零基础入门精选合集(新手必看)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
这个是改版的,不是原文件。