javaSwing实现简单贪吃蛇游戏
效果展示
最外层的窗口是700500
蛇的运行区域是700400
底部的按钮区域是700*100
属性配置Config
。
package snake5;
public class Config {
public final static int ROWS=20;//行
public final static int COLS=35;//列
public final static int SPAN=20;//间隔
public final static String U="U";
public final static String D="D";
public final static String L="L";
public final static String R="R";
public static boolean isLive=true; // true:游戏运行 false:游戏结束
public static boolean isPause=true; // true:游戏运行 false:游戏暂停
public static final String IMAGE_PATH="image/bg1.png";
public static final String BG_MUSIC_PATH="image/bg_music.wav";
}
主界面SnakeGame
。
package snake5;
import javax.swing.JFrame;
public class SnakeGame extends JFrame{
SnakePanel snakePanel = new SnakePanel();
ButtonPanel buttonPanel = new ButtonPanel(snakePanel);
public SnakeGame(){
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds(100, 50, Config.COLS*Config.SPAN, Config.ROWS*Config.SPAN+100);
//不允许改变窗口大小
this.setResizable(false);
this.setLayout(null);
this.setVisible(true);
this.add(snakePanel);
this.add(buttonPanel);
//让 snakePanel获取焦点
snakePanel.setFocusable(true);
snakePanel.requestFocus();
//创建背景音乐
new Music();
}
public static void main(String[] args) {
new SnakeGame();
}
}
蛇运行区域界面 SnakePanel
。
package snake5;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class SnakePanel extends JPanel{
//蛇
Snake snake = new Snake();
//食物
Food food = new Food();
//每间隔200毫秒重置执行一次paint()方法
Snakethread snakethread = new Snakethread();
ImageIcon image = new ImageIcon(Config.IMAGE_PATH);
public SnakePanel(){
this.setBounds(0, 0, Config.COLS*Config.SPAN, Config.ROWS*Config.SPAN);
this.setBackground(Color.BLACK);
snakethread.start();
//添加键盘监听事件
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
snake.keyPressed(e);
}
});
}
@Override
public void paint(Graphics g) {
super.paint(g);
//先画背景,否则背景会把已经画的蛇给覆盖掉
image.paintIcon(this, g, 0, 0);
//蛇移动
snake.move();
//画蛇
snake.draw(g);
//画食物
food.draw(g);
//蛇每次走一步,都去判断一下蛇头是否和食物重叠
snake.eat(food);
//去除网格,美化界面
//g.setColor(Color.darkGray);
/*for(int i=0;i<Config.ROWS;i++){
g.drawLine(0, i*Config.SPAN, Config.COLS*Config.SPAN, i*Config.SPAN);
}
for(int i=0;i<Config.COLS;i++){
g.drawLine(i*Config.SPAN, 0, i*Config.SPAN, Config.ROWS*Config.SPAN);
}*/
}
class Snakethread extends Thread{
@Override
public void run() {
while(Config.isLive){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(Config.isPause){
repaint();
}
}
JOptionPane.showMessageDialog(SnakePanel.this, "游戏结束,再接再厉~~~");
}
}
}
蛇对象 Snake
。
package snake5;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Snake {
Node head;//蛇头
Node tail;//蛇尾
Snake(){
// x y
Node node = new Node(20,5,Config.L);
Node node2 = new Node(21,5,Config.L);
Node node3 = new Node(22,5,Config.L);
node.next=node2;
node2.pre=node;
node2.next=node3;
node3.pre=node2;
head=node;
tail=node3;
}
//蛇移动
public void move(){
//在蛇头前面添加一个节点
addToHead();
//把蛇尾的节点删除,同时让蛇尾前一个节点作为新的尾部
deleteTail();
//每次移动后检测一次是否撞墙
isDied();
}
//判断蛇是否超出了四周的墙
public void isDied(){
if(head.x < 0 || head.x>Config.COLS-1 || head.y<0 || head.y>Config.ROWS-1){
Config.isLive=false;
}
}
//添加到头部
public void addToHead(){
Node node = null;
switch(head.dir){
case Config.L:
node = new Node(head.x-1,head.y,head.dir);
break;
case Config.R:
node = new Node(head.x+1,head.y,head.dir);
break;
case Config.D:
node = new Node(head.x,head.y+1,head.dir);
break;
case Config.U:
node = new Node(head.x,head.y-1,head.dir);
break;
}
node.next=head;
head.pre=node;
head=node;
}
//删除尾部节点
public void deleteTail(){
tail.pre.next=null;
tail = tail.pre;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
switch(key){
case KeyEvent.VK_UP:
if(head.dir.equals(Config.D)){
return;
}
head.dir=Config.U;
break;
case KeyEvent.VK_LEFT:
if(head.dir.equals(Config.R)){
return;
}
head.dir=Config.L;
break;
case KeyEvent.VK_RIGHT:
if(head.dir.equals(Config.L)){
return;
}
head.dir=Config.R;
break;
case KeyEvent.VK_DOWN:
if(head.dir.equals(Config.U)){
return;
}
head.dir=Config.D;
break;
}
}
//Rectangle(x,y,w,h)
//蛇头所在的区域
public Rectangle getRec(){
return new Rectangle(head.x*Config.SPAN,head.y*Config.SPAN,Config.SPAN,Config.SPAN);
}
//蛇吃食物的方法
public void eat(Food food) {
//判断2个区域是否相交
if(this.getRec().intersects(food.getRec())){
this.addToHead();
food.appear();
}
}
public void draw(Graphics g){
for(Node n=head;n!=null;n=n.next){
n.draw(g);
}
}
class Node{
int x;
int y;
Node next;
Node pre;
String dir;
Node(int x,int y,String dir){
this.x=x;
this.y=y;
this.dir=dir;
}
public void draw(Graphics g){
System.out.println(x +" "+y);
g.setColor(Color.yellow);
g.fillOval(x*Config.SPAN,y*Config.SPAN,Config.SPAN, Config.SPAN);
}
}
}
食物对象 Food
package snake5;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
public class Food {
int x;
int y;
Food(){
x=10;
y=8;
}
public void draw(Graphics g){
g.setColor(Color.red);
g.fillRect(x*Config.SPAN, y*Config.SPAN, Config.SPAN, Config.SPAN);
}
//食物所在的区域
public Rectangle getRec(){
return new Rectangle(x*Config.SPAN,y*Config.SPAN,Config.SPAN,Config.SPAN);
}
//让食物重新出现在一个位置
public void appear(){
// 0<=r<1 0 34
x = (int)(Math.random()*Config.COLS) ;
y = (int)(Math.random()*Config.ROWS);
}
}
按钮面板 ButtonPanel
package snake5;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class ButtonPanel extends JPanel{
SnakePanel snakePanel;
public ButtonPanel(SnakePanel snakePanel){
this.snakePanel=snakePanel;
this.setBounds(0, Config.ROWS*Config.SPAN, Config.COLS*Config.SPAN, 100);
JButton pause = new JButton("暂停游戏");
JButton con = new JButton("继续游戏");
JButton restart = new JButton("重新游戏");
this.add(pause);this.add(con);this.add(restart);
pause.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Config.isPause=false;
}
});
con.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Config.isPause=true;
//让 snakePanel获取焦点
snakePanel.setFocusable(true);
snakePanel.requestFocus();
}
});
restart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//让 snakePanel获取焦点
snakePanel.setFocusable(true);
snakePanel.requestFocus();
//运行中不允许重新开始
if(Config.isLive){
return ;
}
//初始化蛇和食物对象
snakePanel.snake=new Snake();
snakePanel.food=new Food();
Config.isLive = true;
Config.isPause = true;
//重新启动线程
snakePanel.snakethread = snakePanel.new Snakethread();
snakePanel.snakethread.start();
}
});
}
}
设置背景音乐Music
package snake5;
import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
public class Music {
public Music(){
try {
//Java播放背景音乐需要无损音质,后缀名 .wav这之类的
File f= new File(Config.BG_MUSIC_PATH);
URI uri = f.toURI();
URL url = uri.toURL();//解析地址
AudioClip aau= Applet.newAudioClip(url);
aau.loop(); //循环播放
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}