贪吃大作战小游戏的 Java 实现(完整教程 + 源代码)积分和变速功能的额外实现(下一步)
最编程
2024-04-20 18:00:33
...
package snakegame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.Random;
//贪吃蛇游戏面板的绘制
public class GamePanel extends JPanel {
Timer timer;
int time=100;
static int score;//记录游戏分数
//蛇属性部分
boolean isDied;
int length;//设置蛇长
String direction;//蛇头朝向
//分别储存蛇身的X,Y坐标
int[] snakeX=new int[300];
int[] snakeY=new int[300];
//判断游戏是否开始
boolean isStart=false;
int foodX,foodY;//食物的X,Y坐标
//贪吃蛇初始化方法
public void init(){
length=3;
snakeX[0]=175;
snakeY[0]=275;
snakeX[1]=150;
snakeY[1]=275;
snakeX[2]=125;
snakeY[2]=275;
foodX=300;
foodY=400;
score=0;
isDied=false;//蛇默认状态为活着
direction="R";//U,D,L,R分别表示蛇头朝向上,下,左,右
}
//构造方法
public GamePanel() throws IOException {
init();
if(GamePanel.score>HighestScore.score){
new HighestScore().highest();
}
//焦点定位到当前面板
this.setFocusable(true);
//监听器的实现部分
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int keyCode = e.getKeyCode();
//按下空格以开始游戏,以及方向键的控制
if (keyCode == KeyEvent.VK_SPACE) {
if(isDied){
init();
}else {
isStart = !isStart;
repaint();//重绘
}
} else if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_W) {
direction = "U";
} else if (keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_S) {
direction = "D";
} else if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_A) {
direction = "L";
} else if (keyCode == KeyEvent.VK_RIGHT || keyCode == KeyEvent.VK_D) {
direction = "R";
}
}
});
//贪吃蛇加速功能的实现
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode=e.getKeyCode();
if(keyCode==KeyEvent.VK_F){
time=10;
timer.setDelay(time);//按下F时加速
}
}
@Override
public void keyReleased(KeyEvent e) {
int keyCode=e.getKeyCode();
if(keyCode==KeyEvent.VK_F){
time=100;
timer.setDelay(time);//松开F键减速恢复默认速度
}
}
});
//对定时器进行初始化,并实现监听器
timer = new Timer(time, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//当游戏处于开始状态且蛇活着时蛇活动,且后一节身子到前一节身子的位置上(每一节身子为25乘25像素)
if (isStart && isDied == false) {
//蛇身运动部分
for (int i = length - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
//蛇头运动部分
if ("D".equals(direction)) {
snakeY[0] += 25;
}
if ("U".equals(direction)) {
snakeY[0] -= 25;
}
if ("L".equals(direction)) {
snakeX[0] -= 25;
}
if ("R".equals(direction)) {
snakeX[0] += 25;
}
//防止超出边界
if (snakeX[0] > 750) {
snakeX[0] = 25;
}
if (snakeX[0] < 25) {
snakeX[0] = 750;
}
if (snakeY[0] < 100) {
snakeY[0] = 725;
}
if (snakeY[0] > 725) {
snakeY[0] = 100;
}
//吃食物的动作,吃食物加10分且蛇身变长,蛇的速度提升10
if ((snakeX[0] == foodX && snakeY[0] == foodY)) {
length++;//蛇身长度加1
foodX = (new Random().nextInt(30) + 1) * 25;//随机生成X坐标[25,750]
foodY = (new Random().nextInt(26) + 4) * 25;//随机生成Y坐标[100,725]
score += 10;//吃一次食物积分加10
try {
new HighestScore().highest();
} catch (IOException ioException) {
ioException.printStackTrace();
}
if(time>10)
timer.setDelay(time-=10);//吃一次食物速度增加10
}
//蛇的死亡机制判定
for (int i = 1; i < length; i++) {
if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
isDied = !isDied;
}
}
repaint();
}
}
});
timer.start();//定时器启动
}
//绘制面板部分
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//填充背景颜色
this.setBackground(new Color(164, 219, 246));
//绘制初始蛇头的图片(默认右方朝向)
Images.backImg.paintIcon(this,g,10,10);
//调整画笔的颜色并绘制一个矩形面板
g.setColor(new Color(219,226,219));
g.fillRect(10,70,770,685);
//蛇头的绘制;上下左右不同情况
if("L".equals(direction)){
Images.snakeLeftImg.paintIcon(this,g,snakeX[0],snakeY[0]);
}
if("R".equals(direction)){
Images.snakeRightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
}
if("U".equals(direction)){
Images.snakeUpImg.paintIcon(this,g,snakeX[0],snakeY[0]);
}
if("D".equals(direction)){
Images.snakeDownImg.paintIcon(this,g,snakeX[0],snakeY[0]);
}
//蛇身的绘制
for(int i=1;i<length;i++) {
Images.bodyImg.paintIcon(this, g, snakeX[i], snakeY[i]);
}
//食物绘制
Images.foodImg.paintIcon(this,g,foodX,foodY);
//游戏的文字提示语
if(!isStart&&!isDied){
g.setColor(new Color(12, 191, 222));
g.setFont(new Font("楷体",Font.BOLD,40));
g.drawString("轻按空格以开始/暂停游戏!",150,330);
g.setColor(new Color(246, 2, 31));
g.setFont(new Font("宋体",Font.CENTER_BASELINE,30));
g.drawString("按住F以加速",300,380);
}
//游戏的得分显示
g.setColor(new Color(248, 4, 74));
g.setFont(new Font("楷体",Font.BOLD,30));
g.drawString("得分:"+score,420,90);
//游戏的最高分展示模块
try {
new HighestScore().readHighest();
} catch (IOException e) {
e.printStackTrace();
}
g.setColor(new Color(183, 25, 238));
g.setFont(new Font("楷体",Font.BOLD,30));
g.drawString("历史最高分:"+HighestScore.score,10,90);
//蛇的速度提示
g.setColor(new Color(248, 136, 36));
g.setFont(new Font("楷体",Font.BOLD,30));
g.drawString("当前速度:"+String.valueOf(110-time),550,90);
//游戏的奖励鼓励机制
if(score==10){
g.setColor(new Color(127, 232, 20));
g.setFont(new Font("微软雅黑",Font.BOLD,50));
g.drawString("Good!",snakeX[0],snakeY[0]);
}
else if(score==50){
g.setColor(new Color(17, 231, 250));
g.setFont(new Font("微软雅黑",Font.BOLD,50));
g.drawString("Good!!!",snakeX[0],snakeY[0]);
}else if(score==100){
g.setColor(new Color(248, 196, 6));
g.setFont(new Font("微软雅黑",Font.BOLD,50));
g.drawString("Perfect!!!",snakeX[0],snakeY[0]);
}else if(score==200){
g.setColor(new Color(248, 245, 26));
g.setFont(new Font("微软雅黑",Font.BOLD,50));
g.drawString("无人能挡!!!",snakeX[0],snakeY[0]);
}
//小蛇死亡时面板的绘制
if(isDied){
g.setColor(new Color(6, 115, 248));
g.setFont(new Font("微软雅黑",Font.BOLD,30));
g.drawString("你的小蛇已经死亡,按下空格重新开始!",170,330);
}
}
}