Java写的第一个小游戏(续)

优化代码(数据维护):

注:此为小游戏最终版本 代码做到最优最简

  • 基于之前发表的文章详情可见

    点击查看前文

  • 回顾之前的代码我们可以看到很多的固定常量值或是属性我们都会大量的重复使用,这并不符合我们代码简洁易懂的特点

  • 所以我们可以把重复出现的量或是属性或是方法使用面向对象的思想,减少代码的冗余使代码简单明了

1.创建项目(GreenHat)

2.在项目(GreenHat)下插入我们使用的图片文件(images)

3.在src(源代码)下创建游戏包(com.ytzl.ylm)

4.在游戏包(com.ytzl.ylm)下创建客户端类(GameClient)以做运行游戏的基础

5.在游戏包下创建项目涉及到类的包(entity)

5.实现游戏窗口

     5.1让客户端类(GameClient)继承Frame类:
public class GameClient extends Frame{
      }

关于Farme类:
1.Farme类是Java自带的一个系统类
2.Farme类的作用是可以制作出带有标题和边框的顶层窗口

     5.2在类包(entity)下创建一个超类(SuperSoulEntity)以存放复用的属性以及代码,减少代码冗余
     5.3在超类下定义之后会多次使用到的窗体的 宽 高
//窗体宽度
    public static final int CLIENT_WIDTH = 700;
    //窗体高度
    public static final int CLIENT_HEIGHT = 500;

使用static定义 以便在其他类调用属性

     5.4在客户端类中写游戏运行方法
// 运行游戏方法
    public void start() {
     
        //开始游戏时在控制台输出显示内容
        System.out.println("游戏马上开始,请玩家做好准备");
        //设置窗体标题
        this.setTitle("原谅帽带战");
        //设置窗体的大小以及位置
        this.setBounds(0, 0, SuperSoulEntity.CLIENT_WIDTH, SuperSoulEntity.CLIENT_HEIGHT);
        // 让窗体显示出来
        this.setVisible(true);
        //点击窗口x关闭键响应关闭
        this.addWindowListener(new WindowAdapter() {
     
            @Override
            public void windowClosing(WindowEvent windowEvent) {
     
                //点击X退出游戏后在控制台输出显示内容
                System.out.println("Game Over!!!");
                //调用System类中的exit方法以实现窗口关闭按钮(X)的生效
                System.exit(0);
            }
        });
     5.5在客户端类中写main方法调用游戏运行方法,实现游戏的运行
//定义main方法以开始运行游戏
    public static void main(String[] args) {
     
        GameClient gameClient = new GameClient();
        gameClient.start();
    }
  • 实现后效果
    Java写的第一个小游戏(续)_第1张图片

6.给窗口添加背景图片

     6.1在超类中定义读取图片的方法以插入图片
//读取图片方法getImage
    public static Image getImage(String imgPath) {
     
        //参数为图片路径地址
        ImageIcon imageIcon = new ImageIcon(imgPath);
        return imageIcon.getImage();
    }
     6.2在客户端类中实现背景图片的插入
	// 常量 定义背景图片的路径
    public static final String BG_PATH = "images/bg.png";

    // 定义一个图片的静态变量
    private static Image image;

    // 把路径的值给静态变量,所有资源(图片,音频,视频)只需要加载一次
    static {
     
        image = SuperSoulEntity.getImage(BG_PATH);
    }

    //重写父类Frame类的paint方法以实现插入各种图片
    @Override
    public void paint(Graphics g) {
     
        // 画背景图
        g.drawImage(image, 0, 0, SuperSoulEntity.CLIENT_WIDTH, SuperSoulEntity.CLIENT_HEIGHT, this);
    }
  • 实现后效果图
    Java写的第一个小游戏(续)_第2张图片

7.插入人物图片

     7.1在类包(entity)下创建人物类(Buffon)
     7.2在超类中写人物用到的属性以及方法
	//x坐标
    protected int x;
    //y坐标
    protected int y;
    //宽
    protected int width;
    //高
    protected int height;
    //移动速度
    protected int speed;
    //游戏窗体属性 使图片在窗体中显示
    protected GameClient gameClient;

    //全参构造    给图片属性赋初始值
    public SuperSoulEntity (int x,int y,int width,int height,int speed,GameClient gameClient) {
     
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.speed = speed;
        this.gameClient = gameClient;
    }
     7.3在人物类中写相应的方法以及属性
// 人物图片属性
    public static Image buffoonImage = SuperSoulEntity.getImage("images/body/s-left.png");
    //带参构造
    public Buffoon(int x, int y, GameClient gameClient) {
     
        super(x, y, 50, 50, 5, gameClient);
    }
    //小丑有自己的画画方法
    public void paint(Graphics g) {
     
        g.drawImage(buffoonImage, this.x, this.y, this.width, this.height, this.gameClient);
    }
     7.4在客户端类中实现插入人物图片
//重写父类Frame类的paint方法以实现插入各种图片
    @Override
    public void paint(Graphics g) {
     
        // 将人物插入窗口
        buffoon.paint(g);
    }
  • 实现效果:
  • Java写的第一个小游戏(续)_第3张图片

8.实现人物移动

     8.1定义图片移动涉及的属性
	// 人物-状态(初始值为静止)
    private String dir = "STOP";
    // 人物-方向
    private String dir1 = "UP";
    //判断方向按键是否同时按下了两个组合键(斜方向移动)默认四个方向都没有被按下
    boolean up = false;
    boolean right = false;
    boolean left = false;
    boolean down = false;
     8.2定义人物-状态的get set方法
//get set方法
    public String getDir() {
     
        return dir;
    }

    public void setDir(String dir) {
     
        this.dir = dir;
    }
     8.3在游戏包下创建线程包(thread)并创建线程类(RepaintTread)接口Runnable,以实现人物图像的移动
/**
 * 线程类(重新绘制画图的线程)
 */
public class RepaintThread implements Runnable{
     
    public RepaintThread(GameClient gameClient) {
     
        this.gameClient = gameClient;
    }

    // 游戏窗体
    private GameClient gameClient;

    @Override
    public void run() {
     
        while (true){
     
            // 每50毫秒执行一次
            try {
     
                Thread.sleep(50);
                // 重新绘制图像
                gameClient.repaint();
            } catch (InterruptedException e) {
     
                e.printStackTrace();
            }
        }
    }
}
     8.4在人物类写相关的移动方法

    // 确定键盘按下时的人物移动方向
    public void okDirPrssed(int keyCode) {
     
        // 确定方向
        switch (keyCode) {
     
            case KeyEvent.VK_UP:
                System.out.println("向上走!");
                // 按向上箭头,给人物的方向设置为向上
                this.setDir("UP");
                // 当按住下方向键时,监听为true(已按下)
                up = true;
                break;
            case KeyEvent.VK_DOWN:
                System.out.println("向下走!");
                // 按向下箭头,给人物的方向设置为向下
                this.setDir("DOWN");
                // 当按住下方向键时,监听为true(已按下)
                down = true;
                break;
            case KeyEvent.VK_LEFT:
                System.out.println("向左走!");
                // 按向左箭头,给人物的方向设置为向左
                this.setDir("LEFT");
                // 当按住下方向键时,监听为true(已按下)
                left = true;
                break;
            case KeyEvent.VK_RIGHT:
                System.out.println("向右走!");
                // 按向右箭头,给人物的方向设置为向右
                this.setDir("RIGHT");
                // 当按住下方向键时,监听为true(已按下)
                right = true;
                break;
        }
        //判断用户到底按了那些键
        //东北
        if (up && right) {
     
            this.setDir("UR");
        }
        //东南
        if (right && down) {
     
            this.setDir("DR");
        }
        //西北
        if (left && up) {
     
            this.setDir("LU");
        }
        //西南
        if (left && down) {
     
            this.setDir("LD");
        }
    }

    /**
     * 键盘松开,确定人物移动方向
     */
    public void okDirReleased(int keyCode) {
     
        switch (keyCode) {
     
            //上
            case KeyEvent.VK_UP:
                up = false;
                break;
            //下
            case KeyEvent.VK_DOWN:
                down = false;
                break;
            //左
            case KeyEvent.VK_LEFT:
                left = false;
                buffoonImage = SuperSoulEntity.getImage("images/body/s-left.png");
                break;
            //右
            case KeyEvent.VK_RIGHT:
                right = false;
                buffoonImage = SuperSoulEntity.getImage("images/body/s-right.png");
                break;
        }
        if (!up&&!down&&!left&&!right){
     
            this.setDir("STOP");
        }
    }

    /**
     * 人物移动
     */
    public void move(String dir) {
     
        if ("UP".equals(dir)) {
     
            this.y -= this.speed;
            dir1="UP";
        }
        if ("RIGHT".equals(dir)) {
     
            this.x += this.speed;
            dir1="RIGHT";
        }
        if ("DOWN".equals(dir)) {
     
            this.y += this.speed;
            dir1="DOWN";
        }
        if ("LEFT".equals(dir)) {
     
            this.x -= this.speed;
            dir1="LEFT";
        }
        if ("UR".equals(dir)) {
     
            this.x += this.speed;
            this.y -= this.speed;
            dir1="UR";
        }
        if ("DR".equals(dir)) {
     
            this.x += this.speed;
            this.y += this.speed;
            dir1="DR";
        }
        if ("LD".equals(dir)) {
     
            this.x -= this.speed;
            this.y += this.speed;
            dir1="LD";
        }
        if ("LU".equals(dir)) {
     
            this.x -= this.speed;
            this.y -= this.speed;
            dir1="LU";
        }
    }
     8.5在客户端类中实现人物移动(补充游戏运行方法)
// 运行游戏方法
    public void start() {
     
        //开始游戏时在控制台输出显示内容
        System.out.println("游戏马上开始,请玩家做好准备");
        //设置窗体标题
        this.setTitle("原谅帽带战");
        //设置窗体的大小以及位置
        this.setBounds(0, 0, SuperSoulEntity.CLIENT_WIDTH, SuperSoulEntity.CLIENT_HEIGHT);
        // 让窗体显示出来
        this.setVisible(true);
        //点击窗口x关闭键响应关闭
        this.addWindowListener(new WindowAdapter() {
     
            @Override
            public void windowClosing(WindowEvent windowEvent) {
     
                //点击X退出游戏后在控制台输出显示内容
                System.out.println("Game Over!!!");
                //调用System类中的exit方法以实现窗口关闭按钮(X)的生效
                System.exit(0);
            }
        });
        // 监听键盘事件
        this.addKeyListener(new KeyAdapter() {
     
            //当键盘按下时触发
            @Override
            public void keyPressed(KeyEvent e) {
     
                // 获取被按下的键的对应数值  如:A-67,B-68
                int keyCode = e.getKeyCode();
                // 调用人物确定方向的方法okDir
                buffoon.okDirPrssed(keyCode);
                buffoon.move(buffoon.getDir());
            }

            //当键盘松开时触发
            @Override
            public void keyReleased(KeyEvent e) {
     
                //获取松开的按键的值
                int keyCode = e.getKeyCode();
                buffoon.okDirReleased(keyCode);
            }
        });

        //开启重新绘制线程
        RepaintThread repaintThread = new RepaintThread(this);
        // 创建车间工人
        Thread thread = new Thread(repaintThread);
        // 工人听候调度
        thread.start();
    }

你可能感兴趣的:(游戏,java)