前言
GUI学习时模仿狂神写的一款贪吃蛇游戏,虽然简单,但也如潮水一般敲打了当时初学的心,让我对Java的学习,有了更深的渴望,让我从一年黑框框编程第一次转向GUI编程。
一、效果图
在狂神原有的基础上,增加了一定的长度,速度会加快。
编程的思想:其实很简单,不过是二维方格的移动,如果把速度放慢,这就是一帧帧的图片,那么如何把一帧帧的图片"动起来"呢?这就用到了定时器。
初次之外,本程序还用到了键盘事件,即上下左右可以控制方向,空格可以控制开始,如何实现这一功能,如何让程序知道我按下了这些键,这就需要键盘事件的监听。
有了键盘事件的监听,如何让小蛇动起来呢??这就用到了简单是数学计算,因为蛇头蛇身,是有固定大小的方块组成的,我只需要更改图片的位置,既可以实现蛇的移动,而且对于整个蛇而言,蛇身是根据蛇头的移动而移动,所以只需要控制蛇头。对于蛇头而言,上下左右的蛇头的方向也是不一样的,所以按下键盘同时也要更换蛇头。
当蛇身出去边界的时候,会从另一端在进入,这里可以用到取余操作。当然也可以手动赋值。
这个程序,基本上难点重点都在这里了。
二、源代码
Data.java
package TCS;
import javax.swing.*;
import java.net.URL;
public class Data {
public static URL headerURl = Data.class.getResource("/TCS/header.png");
public static ImageIcon headerImg = new ImageIcon(headerURl);
public static URL upURl = Data.class.getResource("/TCS/up.png");
public static ImageIcon upImg = new ImageIcon(upURl);
public static URL downURl = Data.class.getResource("/TCS/down.png");
public static ImageIcon downImg = new ImageIcon(downURl);
public static URL leftURl = Data.class.getResource("/TCS/left.png");
public static ImageIcon leftImg = new ImageIcon(leftURl);
public static URL rightURl = Data.class.getResource("/TCS/right.png");
public static ImageIcon rightImg = new ImageIcon(rightURl);
public static URL bodyURl = Data.class.getResource("/TCS/body.png");
public static ImageIcon bodyImg = new ImageIcon(bodyURl);
public static URL foodURl = Data.class.getResource("/TCS/food.png");
public static ImageIcon foodImg = new ImageIcon(foodURl);
}
GameRun.java
package TCS;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class GameRun extends JPanel implements KeyListener, ActionListener {//继承了面板
//对蛇初始化,有蛇头,还要有身子,身子又蛇头更新的
int lenth;
Boolean Isover;
int[] x = new int[600];
int[] y = new int[600];
int Foodx[] = new int[20];
int Foody[] = new int[20];
String fx;
int score;
Boolean Isstart = false;
Timer timer = new Timer(100, this);
Timer timer1 = new Timer(70, this);
Timer timer2 = new Timer(50, this);
Random random = new Random();
public GameRun() {//构造器
Init();
//监听键盘
this.setFocusable(true);//获得焦点事件
this.addKeyListener(this);
//获得
if (lenth < 10) {
timer.start();
} else {
timer.stop();
timer1.start();
}
}
public void Init() {
x[0] = 100;
y[0] = 100;
x[1] = 75;
x[2] = 50;
y[1] = 100;
y[2] = 100;
score = 0;
lenth = 3;
fx = "R";
for (int i = 0; i < 10; i++) {
Foodx[i] = 25 + 25 * random.nextInt(30);
Foody[i] = 75 + 25 * random.nextInt(20);
}
Isover = false;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);//清屏
this.setBackground(Color.WHITE);
Data.headerImg.paintIcon(this, g, 25, 11);
g.setFont(new Font("微软雅黑", Font.BOLD, 18));
g.drawString("长度" + lenth, 750, 30);
g.drawString("分数" + score, 750, 53);
g.fillRect(25, 75, 850, 600);//画颜色
if (Isstart == false && Isover != true) {
g.setColor(Color.WHITE);
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
g.drawString("请按空格键开始", 320, 250);
}
if (Isover) {
g.setColor(Color.red);
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
g.drawString("任务失败,请重新开始", 320, 250);
}
if (fx == "R") {
Data.rightImg.paintIcon(this, g, x[0], y[0]);
}
if (fx == "D") {
Data.downImg.paintIcon(this, g, x[0], y[0]);
}
if (fx == "L") {
Data.leftImg.paintIcon(this, g, x[0], y[0]);
}
if (fx == "U") {
Data.upImg.paintIcon(this, g, x[0], y[0]);
}
for (int i = 1; i < lenth; i++) {
Data.bodyImg.paintIcon(this, g, x[i], y[i]);
}
if (Isstart)//游戏开始后在画
{
for (int i = 0; i < 10; i++) {
Data.foodImg.paintIcon(this, g, Foodx[i], Foody[i]);
}
}
for (int i = 0; i < 10; i++) {
if (x[0] == Foodx[i] && y[0] == Foody[i]) {
Foodx[i] = 100 + 25 * random.nextInt(30);
Foody[i] = 100 + 25 * random.nextInt(20);
score += 25;
lenth++;
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (lenth > 10&&lenth<20) {
timer.stop();
timer1.start();
timer2.stop();
} else if(lenth<10){
timer1.stop();
timer.start();
timer2.stop();
}else{
timer1.stop();
timer.stop();
timer2.start();
}
if (Isstart) {
for (int i = lenth - 1; i > 0; i--) {
x[i] = x[i - 1];
y[i] = y[i - 1];
}
if (fx == "R") {
x[0] += 25;
if (x[0] > 850) {
x[0] = 25;
}
} else if (fx == "D") {
y[0] += 25;
if (y[0] > 650) {
y[0] = 75;
}
} else if (fx == "L") {
x[0] -= 25;
if (x[0] < 25) {
x[0] = 850;
}
} else {
y[0] -= 25;
if (y[0] < 75) {
y[0] = 650;
}
}
for (int i = 1; i < lenth; i++) {
if (x[0] == x[i] && y[0] == y[i]) {
Isover = true;
Isstart = !Isstart;
repaint();
}
}
repaint();
}
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_SPACE) {
Isstart = !Isstart;
if (Isover) {
Isover = !Isover;
Init();
}
repaint();
}
if (keyCode == KeyEvent.VK_UP) {
fx = "U";
} else if (keyCode == KeyEvent.VK_RIGHT) {
fx = "R";
} else if (keyCode == KeyEvent.VK_DOWN) {
fx = "D";
} else if (keyCode == KeyEvent.VK_LEFT) {
fx = "L";
}
// if(!Isstart)
// {
// Init();
// }
// timer.start();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
GameStart.java
package TCS;
import javax.swing.*;
public class GameStart {
public static void main(String[] args) {
JFrame frame = new JFrame();//创建一个组件
frame.setBounds(10,10,925,745);//设置大小
frame.setResizable(false);//设置为固定大小
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//可以关闭
frame.add(new GameRun());//添加
frame.setVisible(true);
}
}
总结
贪吃蛇是一款经典且开发起来特别简单的游戏项目之一,他的原理不过是将静态的图动态的展示出来,方向改变是速度改变,已经头部图片的改变,仅此而已。但是对于初学者来说,跟着作者的脚步,讲这样一款烙进骨髓的游戏开发出来,其成就感不言而喻。有兴趣开发此游戏可以去B站搜索遇见狂神说,当初我也是跟着他把这个游戏做出来的。为了增加难度,大家也可以发挥自己的想象力,增加一些骚操作。即致敬童年,又毁童年,在技术的加持下,完成童年想做但是没有办法做的事情。冲冲冲~~~~