初学Java GUI编程。所以做个贪吃蛇游戏来练习一下学习的东西。
对于Java这种面向对象的编程语言来说,在编写程序之前一定要做相应的分析,要分析需要研究哪些对象,这些对象中会有哪些属性和方法。
对与贪吃蛇这个小游戏,会包含这几种对象: 蛇、食物、游戏控制器、游戏面板。
下面我们就要分析在这些对象中都包含哪些属性和方法。
首先,先分析蛇这个对象:
蛇会具有的属性为: 蛇的身体,蛇身体的颜色,蛇身体的长度,蛇的生命,蛇的运动方向
在贪吃蛇这个小游戏中,是通过蛇在各个方向的运动寻找食物吃然后增长身体来保证游戏的正常进行的。
这时在蛇这个对象中就会存在这样几个方法:蛇移动的方法,蛇吃东西的方法
然后分析食物这个对象:
食物会有颜色和位置这两个属性,和生成食物的方法
初步的代码规划会这这个样子:
- //Snake.java
- package org.sysit.game.snake;
- import java.awt.Color;
- import java.awt.Point;
- import java.util.ArrayList;
- import java.util.List;
- public class Snake {
- private int length;
- private Color color;
- private List<Point> body = new ArrayList();
- private boolean life = true;
- /**
- * 蛇运动方向
- * @author ZHANGBING
- *
- */
- enum dir{
- UP, RIGHT, DOWN, LEFT
- };
- private dir snakeDir;
- /**
- * 初始化蛇
- * @param length 蛇身长度
- */
- public Snake(int length) {
- }
- public void move(){
- }
- /**
- * 判断蛇是否吃到食物
- * @param head 蛇头
- * @return
- */
- public boolean isSnakeEatFood(Point head){
- return true;
- }
- }
- //Food.java
- package org.sysit.game.snake;
- import java.awt.Color;
- import java.awt.Point;
- public class Food {
- private Color color;
- private Point location;
- /**
- * 生成食物的位置
- * @param snake
- * @return 返回Point
- */
- public Point setLocation(Snake snake) {
- return null;
- }
- }
接下来就是向各个方法中添加实现的代码了:
在蛇这个对象中,首先应该先将把蛇初始化的代码完成,在这里,我是以点的形式将蛇的身体的每个一节存入到蛇身体的List中
- /**
- * 初始化蛇
- * @param length 蛇身长度
- */
- public Snake(int length) {
- this.length = length;
- this.color = Color.YELLOW;
- for(int i = length ; i > 0 ; i--){
- body.add(new Point(0, i-1));
- }
- snakeDir = dir.RIGHT;
- }
接下来最核心的应该算是蛇移动的方法了,我的代码还有很大一部分还需改进,我的方法是将多个操作合并到一个方法中了,大家和自己进行修改
- public void move(){
- Point head = new Point(body.get(0).x, body.get(0).y);
- switch(snakeDir){
- case UP:
- head.x --;
- break;
- case DOWN:
- head.x ++;
- break;
- case LEFT:
- head.y --;
- break;
- case RIGHT:
- head.y ++;
- break;
- }
- int canvas_width = SysConfig.CANVAS_WIDTH / SysConfig.STONE_WIDTH - 2;
- int canvas_height = SysConfig.CANVAS_HEIGHT/ SysConfig.STONE_HEIGHT - 2;
- if( head.x < 0 || head.x > canvas_height-1 || head.y < 0 || head.y > canvas_width-1 ){
- life = false; //蛇die
- JOptionPane.showMessageDialog(null, "游戏结束");
- return;
- } else {
- body.add(0, head);
- if(isSnakeEatFood(head)){
- //没有吃到食物
- body.remove(body.size()-1);
- } else {
- getFood().setLocation(this);
- setScore(getScore()+10);
- }
- for(int i = 1 ; i <= body.size()-1 ; i++){
- Point point = body.get(i);
- if(point.x == head.x && point.y == head.y){
- life = false;
- JOptionPane.showMessageDialog(null, "撞到自己啦~游戏结束");
- //System.exit(0);
- return;
- }
- }
- }
- }
- /**
- * 判断蛇是否吃到食物
- * @param head 蛇头
- * @return
- */
- public boolean isSnakeEatFood(Point head){
- if(this.food.getLocation().x == head.x && this.food.getLocation().y == head.y)
- return false;
- return true;
- }
然后在食物这个对象中,我们需要实现的只有声称食物的方法:
- /**
- * 生成食物的位置
- * @param snake
- * @return 返回Point
- */
- public Point setLocation(Snake snake) {
- location = new Point();
- int canvas_width = SysConfig.CANVAS_WIDTH / SysConfig.STONE_WIDTH - 2;
- int canvas_height = SysConfig.CANVAS_HEIGHT/ SysConfig.STONE_HEIGHT - 2;
- int temp = (int) (Math.random() * 1000) ;
- int rand = temp% (canvas_width * canvas_height - snake.getBody().size()) + 1;
- //int rand = temp% 50 + 1;
- boolean flag ;
- for(int i = 0 ; i < canvas_height ; i++){
- for(int j = 0 ; j < canvas_width ; j++){
- flag = true;
- for(Point point : snake.getBody()){
- //System.out.println("point: ("+ point.x + "," + point.y + ")");
- if(i == point.x && j == point.y){
- flag = false;
- break;
- }
- }
- if(flag){
- rand--;
- if(rand == 0){
- location.x = i;
- location.y = j;
- return location;
- }
- }
- }
- }
- return null;
- }
其他剩下来的操作就都是一些将蛇和食物联系起来的代码:
- //GameController.java
- package org.sysit.game.snake;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import javax.swing.JTextField;
- import javax.swing.Timer;
- public class GameController {
- private Ground ground;
- private Snake snake ;
- private Food food ;
- private Timer timer;
- private boolean pause = false;
- private int score = 0;
- private JTextField txtScore;
- public JTextField getTxtScore() {
- return txtScore;
- }
- public void setTxtScore(JTextField txtScore) {
- this.txtScore = txtScore;
- }
- public GameController(final Snake snake, Food food, final Ground ground) {
- this.snake = snake;
- this.food = food;
- this.ground = ground;
- timer = new Timer(200, new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if(snake.isLife()){
- snake.move();
- if(snake.isLife()){
- score = snake.getScore();
- getTxtScore().setText(score + "");
- ground.repaint();
- } else {
- timer.stop();
- }
- }
- }
- });
- }
- /**
- * 游戏初始化
- */
- public void init(){
- getTxtScore().setText("0");
- }
- /**
- * 开始游戏
- */
- public void startGame(){
- init();
- timer.start();
- ground.requestFocus();
- }
- /**
- * 暂停游戏
- */
- public void pauseGame() {
- if(!pause){
- timer.stop();
- pause = true;
- }
- ground.requestFocus();
- }
- /**
- * 继续游戏
- */
- public void resumeGame() {
- if(pause){
- timer.restart();
- pause = false;
- }
- ground.requestFocus();
- }
- public boolean isPause() {
- return pause;
- }
- public void setPause(boolean pause) {
- this.pause = pause;
- }
- }
- //Ground.java
- package org.sysit.game.snake;
- import java.awt.Canvas;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.Image;
- import java.awt.Point;
- import java.awt.event.KeyAdapter;
- import java.awt.event.KeyEvent;
- import java.util.List;
- import org.sysit.game.snake.Snake.dir;
- public class Ground extends Canvas {
- private Snake snake;
- private Food food;
- private Image iBuffer;
- public Ground() {
- setBounds(0, 0, SysConfig.CANVAS_WIDTH, SysConfig.CANVAS_HEIGHT);
- setBackground(Color.BLACK);
- addKeyListener(new KeyAdapter() {
- @Override
- public void keyPressed(KeyEvent e) {
- int keyCode = e.getKeyCode();
- switch(keyCode){
- case KeyEvent.VK_UP:
- snake.setSnakeDir(dir.UP);
- break;
- case KeyEvent.VK_DOWN:
- snake.setSnakeDir(dir.DOWN);
- break;
- case KeyEvent.VK_LEFT:
- snake.setSnakeDir(dir.LEFT);
- break;
- case KeyEvent.VK_RIGHT:
- snake.setSnakeDir(dir.RIGHT);
- break;
- }
- }
- });
- }
- public Snake getSnake() {
- return snake;
- }
- public void setSnake(Snake snake) {
- this.snake = snake;
- }
- public Food getFood() {
- return food;
- }
- public void setFood(Food food) {
- this.food = food;
- }
- /**
- * 双缓冲技术解决屏幕闪烁问题
- */
- @Override
- public void update(Graphics g) {
- if(iBuffer == null){
- iBuffer = createImage(this.getSize().width, this.getSize().height);
- }
- //if(gBuffer == null){
- Graphics gBuffer = iBuffer.getGraphics();
- //}
- gBuffer.setColor(getBackground());
- gBuffer.fillRect(0, 0, this.getSize().width, this.getSize().height);
- paint(gBuffer);
- gBuffer.dispose();
- g.drawImage(iBuffer, 0, 0, this);
- }
- /**
- * 画墙
- */
- public void drawWall(Graphics g) {
- g.setColor(Color.GRAY);
- int canvas_width = SysConfig.CANVAS_WIDTH / SysConfig.STONE_WIDTH;
- int canvas_height = SysConfig.CANVAS_HEIGHT / SysConfig.STONE_WIDTH;
- for (int i = 0; i < canvas_width ; i++) {
- g.fill3DRect(i * SysConfig.STONE_WIDTH, 0, SysConfig.STONE_WIDTH,
- SysConfig.STONE_HEIGHT, true);
- }
- for (int i = 0; i < canvas_width ; i++) {
- g.fill3DRect(i * SysConfig.STONE_WIDTH, SysConfig.CANVAS_HEIGHT
- - SysConfig.STONE_HEIGHT, SysConfig.STONE_WIDTH,
- SysConfig.STONE_HEIGHT, true);
- }
- for (int i = 0; i < canvas_height ; i++) {
- g.fill3DRect(0, i * SysConfig.STONE_WIDTH, SysConfig.STONE_WIDTH,
- SysConfig.STONE_HEIGHT, true);
- }
- for (int i = 0; i < canvas_height ; i++) {
- g.fill3DRect(SysConfig.CANVAS_WIDTH - SysConfig.STONE_WIDTH, i
- * SysConfig.STONE_WIDTH, SysConfig.STONE_WIDTH,
- SysConfig.STONE_HEIGHT, true);
- }
- }
- /**
- * 画草地
- */
- public void drawGrass(Graphics g) {
- g.setColor(Color.DARK_GRAY);
- for (int i = 1; i < SysConfig.CANVAS_WIDTH / SysConfig.STONE_WIDTH - 1; i++) {
- for (int j = 1; j < SysConfig.CANVAS_HEIGHT
- / SysConfig.STONE_HEIGHT - 1; j++) {
- g.fill3DRect(i * SysConfig.STONE_WIDTH, j
- * SysConfig.STONE_HEIGHT, SysConfig.STONE_WIDTH,
- SysConfig.STONE_HEIGHT, true);
- }
- }
- }
- /**
- * 画食物
- */
- public void drawFood(Graphics g) {
- Point point = getFood().getLocation();
- //System.out.println("location : (" + point.x + "," +point.y +")");
- g.setColor(getFood().getColor());
- g.fill3DRect(( point.y + 1 ) * SysConfig.STONE_WIDTH, (point.x + 1)* SysConfig.STONE_HEIGHT, SysConfig.STONE_WIDTH,SysConfig.STONE_HEIGHT, true);
- }
- /**
- * 画蛇
- */
- public void drawSnake(Graphics g) {
- g.setColor(getSnake().getColor());
- List<Point> body = getSnake().getBody();
- for (Point point : body) {
- g.fill3DRect((point.y + 1) * SysConfig.STONE_WIDTH, (point.x + 1)
- * SysConfig.STONE_HEIGHT, SysConfig.STONE_WIDTH,
- SysConfig.STONE_HEIGHT, true);
- }
- }
- @Override
- public void paint(java.awt.Graphics g) {
- drawWall(g);
- drawGrass(g);
- //snake.move();
- if(snake != null){
- drawSnake(g);
- }
- if(food != null){
- drawFood(g);
- }
- };
- }
- //MainFrame.java
- package org.sysit.game.snake;
- import java.awt.BorderLayout;
- public class MainFrame extends JFrame {
- private JButton start;
- private JButton pause;
- private JPanel panel;
- private JPanel showScore;
- private JLabel lblNewLabel;
- private JTextField txtScore;
- public MainFrame() {
- super("贪吃蛇");
- getContentPane().setLayout(new BorderLayout());
- setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- Ground ground = new Ground();
- //controller.setGround(ground);
- Snake snake = new Snake(3);
- ground.setSnake(snake);
- Food food = new Food();
- ground.setFood(food);
- snake.setFood(food);
- food.setLocation(snake);
- final GameController controller = new GameController(snake, food, ground);
- JPanel control = new JPanel();
- start = new JButton("开始");
- start.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- controller.startGame();
- pause.setEnabled(true);
- }
- });
- start.setSize(100, 50);
- pause = new JButton("暂停");
- pause.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- if(controller.isPause()){
- pause.setText("暂停");
- controller.resumeGame();
- }else{
- pause.setText("继续");
- controller.pauseGame();
- }
- }
- });
- pause.setEnabled(false);
- pause.setSize(100, 50);
- control.add(start);
- control.add(pause);
- add(ground, BorderLayout.CENTER);
- add(control, BorderLayout.SOUTH);
- pack();
- panel = new JPanel();
- control.add(panel);
- panel.setLayout(null);
- showScore = new JPanel();
- getContentPane().add(showScore, BorderLayout.NORTH);
- showScore.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
- lblNewLabel = new JLabel("\u5206\u6570 : ");
- showScore.add(lblNewLabel);
- txtScore = new JTextField();
- showScore.add(txtScore);
- txtScore.setColumns(10);
- txtScore.setEditable(false);
- controller.setTxtScore(txtScore);
- Toolkit tool = Toolkit.getDefaultToolkit();
- Dimension dime = tool.getScreenSize();
- int screenWidth = dime.width;
- int screenHeight = dime.height;
- int frameWidth = SysConfig.CANVAS_WIDTH + 6;
- int frameHeight = SysConfig.CANVAS_HEIGHT + 94;
- setBounds((screenWidth - frameWidth)/2, (screenHeight - frameHeight)/2, frameWidth, frameHeight);
- setResizable(false);
- setVisible(true);
- }
- public static void main(String[] args) {
- new MainFrame();
- }
- }