优化代码(数据维护):
注:此为小游戏最终版本 代码做到最优最简
-
基于之前发表的文章详情可见
点击查看前文
-
回顾之前的代码我们可以看到很多的固定常量值或是属性我们都会大量的重复使用,这并不符合我们代码简洁易懂的特点
-
所以我们可以把重复出现的量或是属性或是方法使用面向对象的思想,减少代码的冗余使代码简单明了
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() {@Overridepublic 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();}
- 实现后效果
6.给窗口添加背景图片
6.1在超类中定义读取图片的方法以插入图片
//读取图片方法getImagepublic 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方法以实现插入各种图片@Overridepublic void paint(Graphics g) {// 画背景图g.drawImage(image, 0, 0, SuperSoulEntity.CLIENT_WIDTH, SuperSoulEntity.CLIENT_HEIGHT, this);}
- 实现后效果图
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方法以实现插入各种图片@Overridepublic void paint(Graphics g) {// 将人物插入窗口buffoon.paint(g);}
- 实现效果:
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;@Overridepublic 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() {@Overridepublic void windowClosing(WindowEvent windowEvent) {//点击X退出游戏后在控制台输出显示内容System.out.println("Game Over!!!");//调用System类中的exit方法以实现窗口关闭按钮(X)的生效System.exit(0);}});// 监听键盘事件this.addKeyListener(new KeyAdapter() {//当键盘按下时触发@Overridepublic void keyPressed(KeyEvent e) {// 获取被按下的键的对应数值 如:A-67,B-68int keyCode = e.getKeyCode();// 调用人物确定方向的方法okDirbuffoon.okDirPrssed(keyCode);buffoon.move(buffoon.getDir());}//当键盘松开时触发@Overridepublic void keyReleased(KeyEvent e) {//获取松开的按键的值int keyCode = e.getKeyCode();buffoon.okDirReleased(keyCode);}});//开启重新绘制线程RepaintThread repaintThread = new RepaintThread(this);// 创建车间工人Thread thread = new Thread(repaintThread);// 工人听候调度thread.start();}