贪吃蛇-----小游戏

贪吃蛇—–小游戏

  • Snake类
    分析Snake类,必须要考虑以下几个问题:
    1,贪吃蛇的身体如何绘制?
    2,位置和方向怎样更新?
    相信你有自己的答案,这里给出经验方法
    1,使用数组存放蛇身(蛇身由实心圆圈连成),数组的长度即为蛇身的最大长度。即将蛇变为数组处理
    2,利用上述数组,保证数组的循环,前一个圆圈的坐标作为下一个圆圈的坐标的更新值。意味着只有蛇头圆圈的坐标需要更新,其余圆圈的坐标直接采用数组上一个圆圈的保存值。
package tcs;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;//导入随机类

public class Food {

    public Point location; // 食物的坐标
    public Point size; // 食物的方块尺寸
    private GamePanel gameP;
    private Snake snk;
    private Random rand;

    public Food(GamePanel gp, Snake sk) {// 初始化各变量
        gameP = gp;
        snk = sk;
        rand = new Random();
        location = new Point(Math.abs(rand.nextInt() % gameP.width), Math.abs(rand.nextInt() % gameP.heigth));
        size = new Point(sk.diameter, sk.diameter);// 尺寸与贪吃蛇圆圈相同
    }

    public void update() {// 判断是否重合,重合则认为Food被蛇吃到
        if ((Math.abs((snk.x + snk.diameter / 2) - (location.x + size.x / 2)) < snk.diameter)
                && (Math.abs((snk.y + snk.diameter / 2) - (location.y + size.y / 2)) < snk.diameter)) {
            location = new Point(Math.abs(rand.nextInt() % gameP.width), Math.abs(rand.nextInt() % gameP.heigth));
            if (snk.length < Snake.MAXLENTH) {
                snk.length++;
            }
        }
    }

    public void draw(Graphics g) {
        g.setColor(Color.black);// 食物是黑色
        g.fillRect(location.x, location.y, size.x, size.y);// 食物用方块绘制
    }
}
  • Food类

分析Food类,同样需要考虑两个问题:
1,怎样判断食物被蛇吃了?
2,事物的坐标如何更新?
对于第一个问题,我们只需检测蛇头是否与食物发生了碰撞,如果两个对象碰到了一起,则认为食物被吃了,执行事物的坐标更新;第二个问题,导入Random随机类,在Panel上产生随机点作为Food的新位置

package tcs;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;//导入随机类

public class Food {

    public Point location; // 食物的坐标
    public Point size; // 食物的方块尺寸
    private GamePanel gameP;
    private Snake snk;
    private Random rand;

    public Food(GamePanel gp, Snake sk) {// 初始化各变量
        gameP = gp;
        snk = sk;
        rand = new Random();
        location = new Point(Math.abs(rand.nextInt() % gameP.width), Math.abs(rand.nextInt() % gameP.heigth));
        size = new Point(sk.diameter, sk.diameter);// 尺寸与贪吃蛇圆圈相同
    }

    public void update() {// 判断是否重合,重合则认为Food被蛇吃到
        if ((Math.abs((snk.x + snk.diameter / 2) - (location.x + size.x / 2)) < snk.diameter)
                && (Math.abs((snk.y + snk.diameter / 2) - (location.y + size.y / 2)) < snk.diameter)) {
            location = new Point(Math.abs(rand.nextInt() % gameP.width), Math.abs(rand.nextInt() % gameP.heigth));
            if (snk.length < Snake.MAXLENTH) {
                snk.length++;
            }
        }
    }

    public void draw(Graphics g) {
        g.setColor(Color.black);// 食物是黑色
        g.fillRect(location.x, location.y, size.x, size.y);// 食物用方块绘制
    }
}
  • GamePanel类

框架的建立十分重要,需要考虑很多问题,如:实现动画效果的帧变化;如何让帧速率稳定有效(创建线程);为何要离屏绘制及如何离屏绘制蛇身和食物等。
为了方便大家实验,这里先给出代码

package tcs;

import java.awt.*;
import java.awt.event.*;

public class GamePanel extends Panel implements Runnable, KeyListener {
    public int width; // 面板宽度
    public int heigth; // 面板高度
    public int incre = 1; // 面板
    private Image im;
    private Graphics dbg;
    private Thread gamethread; // 线程控制游戏运行
    private static final int FPS = 30; // 帧变化速度,表现为蛇移动速度
    private boolean running = false;
    private boolean isPaused = false;
    private int direction;
    public static final int SOUTH = 0; // 后期显示
    public static final int NORTH = 1;
    public static final int EAST = 2;
    public static final int WEST = 3;
    private Snake sk;
    private Food bk;

    public GamePanel() {// 面板初始化
        width = 300;
        heigth = 300;
        setPreferredSize(new Dimension(width, heigth));
        sk = new Snake(this);// 引用
        bk = new Food(this, sk);// 引用
        // 以下三句为按键检测
        setFocusable(true);
        requestFocus();
        addKeyListener(this);
    }

    public int getDirection() {
        return direction;
    }

    public void gameStart() {
        if (!running) {
            gamethread = new Thread(this);
            gamethread.start(); // 启动此线程(实际上只有这一个线程)
        }
    }

    public void gameStop() {
        running = false;
    }

    public void gamePaint() {
        Graphics g;
        try {
            g = this.getGraphics();
            if (g != null && im != null) {
                g.drawImage(im, 0, 0, null);
            }
            g.dispose();
        } catch (Exception e) {
        }
    }

    // 离屏绘制
    public void gameRender() {
        if (im == null) {
            // 建立im对象,进行离屏绘制
            im = createImage(width, heigth);
            if (im == null) {
                System.out.println("im is null");
            } else {
                dbg = im.getGraphics();
            }
        }

        dbg.setColor(Color.white);
        dbg.fillRect(0, 0, width, heigth);
        sk.draw(dbg);
        bk.draw(dbg);

    }

    public void gameUpdate() {

        if (!isPaused) {
            sk.update();
            bk.update();

        }
    }

    // 重载run()方法,将游戏循环放置其中
    public void run() {
        long t1, t2, dt, sleepTime;
        long period = 1000 / FPS; //
        t1 = System.nanoTime(); //
        while (true) {
            gameUpdate();
            gameRender();
            gamePaint();
            t2 = System.nanoTime();
            dt = (t2 - t1) / 1000000L;
            sleepTime = period - dt;
            if (sleepTime <= 0)
                sleepTime = 2;
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException ex) {
            }
            t1 = System.nanoTime();
        }
    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
        int keycode = e.getKeyCode();

        if (keycode == KeyEvent.VK_P) {
            isPaused = !isPaused;
            System.out.println("key is P");
        }

        if (!isPaused) {
            switch (keycode) {

            case KeyEvent.VK_DOWN:
                direction = SOUTH;
                System.out.println("key is down" + direction);
                break;
            case KeyEvent.VK_UP:
                direction = NORTH;
                System.out.println("key is up" + direction);
                break;
            case KeyEvent.VK_RIGHT:
                direction = EAST;
                System.out.println("key is right" + direction);
                break;
            case KeyEvent.VK_LEFT:
                direction = WEST;
                System.out.println("key is left" + direction);
                break;
            }
        }
    }

    public void keyReleased(KeyEvent e) {
    }
}

-Frame类

package tcs;

import java.awt.*;
import java.awt.event.*;

public class GameFrame {

    public GameFrame() {
        Frame app = new Frame("GameFrame");

        app.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        app.setLocation(100, 100);
        GamePanel drawB = new GamePanel();
        app.add(drawB, BorderLayout.CENTER);

        app.pack();
        app.setResizable(false);
        app.setVisible(true);
        drawB.gameStart();
    }

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) {
        new GameFrame();
        // TODO code application logic here
    }
}

实践创建java项目

运行GameFrame.java
这里写图片描述

注:文章转载,转载地址:
http://blog.csdn.net/qq_33232071/article/details/50583572

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值