GUI编程3--贪吃蛇之界面绘制

贪吃蛇

帧:如果时间片足够小,就是动画,一秒30帧。连起来动画,拆开就是静态的图片。
键盘监听
定时器Timer

  1. 定义数据
  2. 画上去
  3. 监听事件
    键盘监听
    事件监听游戏状态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定时频率越快
小蛇撞墙增加失败判断
食物分不同颜色,不同分数身体增长长度不同,或者减少长度,或者小蛇死掉
小蛇转向方向,不能和原来的方向正相反
鼠标控制方向
游戏记录存数据库
连击对战
登录

posted @ 2021-02-05 17:31  晒网达人  阅读(165)  评论(0)    收藏  举报