GUI编程3--贪吃蛇之界面绘制
贪吃蛇
帧:如果时间片足够小,就是动画,一秒30帧。连起来动画,拆开就是静态的图片。
键盘监听
定时器Timer
- 定义数据
 - 画上去
 - 监听事件
键盘监听
事件监听游戏状态timer(每个Timer对象是单个后台线程),按预定频率触发ActionEvent事件的源组件 
回去补图excel表格上画蛇的截图
放图片可以放在跟目录下,也可以放在当前目录下
StratGame.java
package snake;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
// Game start class
public class StartGame {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
			JFrame frame = new JFrame();
			frame.setBounds(10, 10, 900, 720); 
			//size is fixed
			frame.setResizable(false);
			frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
			
			//Game should in panel
			frame.add(new GamePanel());
			
			frame.setVisible(true);
	}
} 
GamePanel.java
package snake;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GamePanel extends JPanel implements KeyListener, ActionListener {
	// snake length
	int length;
	int[] snakeX = new int[600];
	int[] snakeY = new int[500];
	String fx;
	// food coordinate
	int foodx;
	int foody;
	Random random = new Random();
	
	//Score
	int score;
	// game status start or stop,defalut is stop(false)
	boolean isStart = false;
	// game failed?
	boolean isFail = false;
	// Timer 100ms one time,它是一个按预定频率触发ActionEvent事件的源组件,利用它可以实现动态效果
	// Timer( int delay, ActionListener
	// actionListener(绑定监听器每隔delay长的时间,不断调用监听器的actionperformed函数));
	Timer timer = new Timer(200, this);
	// constructer call init method
	public GamePanel() {
		init();
		// get focus
		this.setFocusable(true);
		// get key monitor event
		this.addKeyListener(this);
		timer.start();
	}
	// init method
	public void init() {
		length = 3;
		snakeX[0] = 100;
		snakeY[0] = 100;// head
		snakeX[1] = 75;
		snakeY[1] = 100;// first body block
		snakeX[2] = 50;
		snakeY[2] = 100;// second body block
		fx = "R";
		// put food randomly
		foodx = 25 + 25 * random.nextInt(34);
		foody = 75 + 25 * random.nextInt(24);
		
		score = 0;
	}
	// Paint panel, all the things in our game using this paint brush
	@Override
	protected void paintComponent(Graphics g) {
		// TODO Auto-generated method stub
		super.paintComponent(g);// clear screen
		// paint static panel
		this.setBackground(Color.white);
		Data.header.paintIcon(this, g, 25, 11);
		// paint rectangle
		g.fillRect(25, 75, 850, 600);
		
		//draw score
		g.setColor(Color.white);
		g.setFont(new Font("Microsoft YaHei", Font.BOLD, 15));
		g.drawString("Length: "+ length, 750, 35);
		g.drawString("Score: "+ score, 750, 50);
		
		// draw food
		 Data.food.paintIcon(this, g, foodx, foody);
		// draw head
		if ("R".equals(fx)) {
			// draw static snake, init snake head towards right
			Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
		} else if ("L".equals(fx)) {
			Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
		} else if ("U".equals(fx)) {
			Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
		} else if ("D".equals(fx)) {
			Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
		}
		// draw body
		for (int i = 1; i < length; i++)
			Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
		if (isStart == false) {
			g.setColor(Color.white);
			g.setFont(new Font("Microsoft YaHei", Font.BOLD, 40));
			g.drawString("push spacing to start", 300, 300);
		}
		if (isFail == true) {
			g.setColor(Color.red);
			g.setFont(new Font("Microsoft YaHei", Font.BOLD, 40));
			g.drawString("game failed", 300, 300);
		}
	}
	@Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		int keyCode = e.getKeyCode();
		// if press space button
		if (keyCode == KeyEvent.VK_SPACE) {
			if (isFail) {
				isFail = false;
				init();
			} else {
				isStart = !isStart;
			}
			repaint();
		}
		if (keyCode == KeyEvent.VK_UP) {
			fx = "U";
		} else if (keyCode == KeyEvent.VK_DOWN) {
			fx = "D";
		} else if (keyCode == KeyEvent.VK_LEFT) {
			fx = "L";
		} else if (keyCode == KeyEvent.VK_RIGHT) {
			fx = "R";
		}
	}
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
	}
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
	}
	// evnent monitor use fixed time to refresh, like 10/s
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		if (isStart && isFail == false) {
			if (snakeX[0] == foodx && snakeY[0] == foody) {
				//length & score increase
				length++;
				score += 10;
				
				// create food again
				foodx = 25 + 25 * random.nextInt(34);
				foody = 75 + 25 * random.nextInt(24);
			}
			for (int i = length - 1; i > 0; i--) {
				snakeX[i] = snakeX[i - 1];
				snakeY[i] = snakeY[i - 1];
			}
			if (fx.equals("R")) {
				snakeX[0] += 25;
				// boundary judgement
				if (snakeX[0] > 850) {
					snakeX[0] = 25;
				}
			}
			if (fx.equals("L")) {
				snakeX[0] -= 25;
				// boundary judgement
				if (snakeX[0] < 25) {
					snakeX[0] = 850;
				}
			}
			if (fx.equals("U")) {
				snakeY[0] -= 25;
				// boundary judgement
				if (snakeY[0] < 75) {
					snakeY[0] = 650;
				}
			}
			if (fx.equals("D")) {
				snakeY[0] += 25;
				// boundary judgement
				if (snakeY[0] > 650) {
					snakeY[0] = 75;
				}
			}
			// bump to itself
			for (int i = 1; i < length; i++) {
				if (snakeX[0] == snakeX[i] & snakeY[0] == snakeY[i]) {
					isFail = true;
				}
			}
			repaint();
			// timer.start();
		}
	}
}
Data.java
package snake;
import java.net.URL;
import javax.swing.ImageIcon;
// data center
public class Data {
	//absolute path start with /,current project, relative path
	public static URL headerUrl = Data.class.getResource("statics/header.png");
	public static ImageIcon header = new ImageIcon(headerUrl);
	
	public static URL upUrl = Data.class.getResource("statics/up.png");
	public static URL downUrl = Data.class.getResource("statics/down.png");
	public static URL leftUrl = Data.class.getResource("statics/left.png");
	public static URL rightUrl = Data.class.getResource("statics/right.png");
	public static URL bodyUrl = Data.class.getResource("statics/body.png");
	public static URL foodUrl = Data.class.getResource("statics/food.png");
	
	public static ImageIcon up = new ImageIcon(upUrl);
	public static ImageIcon down = new ImageIcon(downUrl);
	public static ImageIcon left = new ImageIcon(leftUrl);
	public static ImageIcon right = new ImageIcon(rightUrl);
	public static ImageIcon body = new ImageIcon(bodyUrl);
	public static ImageIcon food = new ImageIcon(foodUrl); 
	
}
优化思路 待实现
积分越高等级越高,等级越高timer定时频率越快
小蛇撞墙增加失败判断
食物分不同颜色,不同分数身体增长长度不同,或者减少长度,或者小蛇死掉
小蛇转向方向,不能和原来的方向正相反
鼠标控制方向
游戏记录存数据库
连击对战
登录
    博客有点圆
                    
                
                
            
        
浙公网安备 33010602011771号