成果展示

制作思路

第1步:发现类(对象)

人物-小丑: Buffoon
子弹-帽子:Missile
墙体:Wall
爆炸物:Explode

第2步:发现属性

小丑:宽和高,位置(x,y),移动速度
帽子:宽和高,位置(x,y),移动速度
墙体:宽和高,位置(x,y)
爆炸物:宽和高,位置(x,y)

第3步:发现方法

小丑:移动、攻击、人物撞边界
子弹:移动、子弹撞墙、子弹撞边界
爆炸物:消失

重难点分析

窗体如何创建

public class GameClient extends Frame

通过继承Frame类实现Java窗体

public class Frame extends Window implements MenuContainer

Frame类继承了Window类和MenuContainer接口

如何将图片加载到窗体里

步骤1:创建常用工具类CommonUtils,新建getImage方法实现将图片资源转换为Java对象

public class CommonUtils {/*** 读取图片资源, 转变为Java对象 Image* @param imgPath  图片路径* @return Image对象*/public static Image getImage(String imgPath) {ImageIcon imageIcon = new ImageIcon(imgPath);return imageIcon.getImage();}
}

步骤2:调用getImage方法添加对象图片

public class GameClient extends Frame {Image bg_image = CommonUtils.getImage("images/bg.png");Image explode = CommonUtils.getImage("images/explode.png");Image missile = CommonUtils.getImage("images/missile.png");Image wall_h = CommonUtils.getImage("images/wall-h.png");Image wall_v = CommonUtils.getImage("images/wall-v.png");Image buffoon = CommonUtils.getImage("images/body/s-left.png");

步骤3:重写Framed的paint方法,实现窗体加载图片

@Overridepublic void paint(Graphics g){//画背景图g.drawImage(bg_image,0,0,1100,700,this);//画小丑g.drawImage(buffoon,300,200,80,80,this);//画爆炸物g.drawImage(explode,800,400,90,90,this);//画原谅帽g.drawImage(missile,300,300,60,60,this);//画横着的墙体g.drawImage(wall_h,400,300,100,20,this);//画竖着的墙体g.drawImage(wall_v,400,300,20,100,this);

Graphics类的drawImage方法需要提供Image类参数、窗体的x参数、窗体的y参数、Image类的宽度width、Image类的长度length以及observer(当转换了更多图像时要通知的对象)

对象移动的实现

指向标的地图,通常采用“上北下南,左西右东”的规则确定方向。移动的八个方向通常指的是北、东北、东、东南、南、西南、西、西北。因此在定义移动方向时用上、左、下、右、上右、下右、上左、下左来表示

小丑:移动  move<Orientation类传递方向参数>
'left向左'   :x = x - this.speed;
'right向右'  :x = x + this.speed;
'down向下'   :y = y + this.speed;
'up向上'     :y = y - this.speed;
'ur东北方向'  : x = x + this.speed;y = y - this.speed;
'ul西北方向'  : x = x - this.speed;y = y - this.speed;
'dr东南方向'  : x = x + this.speed;y = y + this.speed;
'dl西南方向'  : x = x - this.speed;y = y + this.speed;

窗体关闭的实现

    public void start() {//窗体添加侦听方法this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {super.windowClosing(e);//退出游戏System.exit(0);}});

WindowAdapter类
1.接收窗口事件的抽象适配器类。此类中的方法为空。此类存在的目的是方便创建侦听器对象。
2.扩展此类可创建 WindowEvent 侦听器并为所需事件重写该方法。(如果要实现 WindowListener 接口,则必须定义该接口内的所有方法。此抽象类将所有方法都定义为 null,所以只需针对关心的事件定义方法。
3.使用扩展的类可以创建侦听器对象,然后使用窗口的 addWindowListener 方法向该窗口注册侦听器。当通过打开、关闭、激活或停用、图标化或取消图标化而改变了窗口状态时,将调用该侦听器对象中的相关方法,并将 WindowEvent 传递给该方法。
windowAdapter监听器

按键事件触发的实现

 this.addKeyListener(new KeyAdapter() {//键盘按下的时候出发@Overridepublic void keyPressed(KeyEvent e) {super.keyPressed(e);}//键盘松开@Overridepublic void keyReleased(KeyEvent e) {//获取被按下的键对应的数值,如,a:67,b:68int keyCode = e.getKeyCode();switch (keyCode){case KeyEvent.VK_UP:System.out.println("向上走!!!");buffoon.setDir("UP");break;case KeyEvent.VK_DOWN:System.out.println("向下走");buffoon.setDir("DOWN");break;case KeyEvent.VK_RIGHT:System.out.println("向右走");buffoon.setDir("RIGHT");break;case KeyEvent.VK_LEFT:System.out.println("向左走!!");buffoon.setDir("LEFT");break;}buffoon.move(buffoon.getDir());}});

按键触发的要点

要点一:‘new KeyAdapter()’ 新建一个按键事件的监听器,并通过addKeyListener()向主窗体注册该监听器;
要点二:重写KeyAdapter的方法,分别是KeyTyped(键入)、KeyPresdded(按下)、KeyReleased(释放)。这里我们只监听KeyPressed事件并重写该方法,实现对人物方向状态的改变;
要点三:KeyEvent e.getKeyCode返回的是按下按键对应的键值,参考KeyEvent的键值属性。Java 8在线API

创建对象Buffoon.move()方法

    public void move(String dir){switch (dir){case "UP":this.y -= this.speed;setDir("STOP");break;case "DOWN":this.y += this.speed;setDir("STOP");break;case "RIGHT":this.x += this.speed;setDir("STOP");break;case "LEFT":this.x -= this.speed;setDir("STOP");break;}

每次监听到按键事件调用move方法实现buffoon对象的移动

对象移动的原理

对象移动的画面也叫动画,是在屏幕上显示一系列连续动画画面的一帧一帧的图形,然后在间隔很短的时间显示下一帧图形,如此反复,利用人眼的‘视觉暂留’现象主观感觉好像画面的物体在运动。
FPS(Frames Per Second),是每秒钟的帧数。一帧就是一幅静态画像,电影的播放速度是24FPS。帧数越多,所显示的动作就会越流畅。通常,要避免动作不流畅的最低是30FPS。FPS百度百科

动画移动的搬运工-线程(thread)

什么是线程
线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

/*** 定义一个重新绘制画面的线程,相当于招一个工人专门去从事这项工作*/
public class RePaintThread implements Runnable{@Override//线程操作的全都在run方法中public void run() {while (true){//每50毫秒 执行一次try {Thread.sleep(20);//重新绘制图像gameClient.repaint();} catch (InterruptedException e) {e.printStackTrace();}}}

要点一:Runnable接口
public class RePaintThread implements Runnable
使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。
要点二:重写Run方法
方法 run 的常规协定是:它可能执行任何所需的动作。
重新绘制图像
gameClient.repaint();
要点三:Thread.sleep—线程反复执行的时间间隔
1、使用’While(true)'构造死循环
2、在死循环中执行repaint()重绘图形方法
3、线程中断异常(InterruptedException)是当前线程被中断的表现之一。遇到这个异常时,如果你不知道如何处理,你应当向上抛出。

子弹发射的实现

Buffoon类

//子弹容器private List<Missile> missileList=new ArrayList<Missile>();//开火
public Missile fire(){//人物在哪里,子弹就在哪发射return new Missile(this.x,this.y,this.dir,this.gameClient);}
//根据按键输入内容完成buffoon的动作
public void okDirPressed(int keyCode){//TODO 确定方向switch (keyCode){case KeyEvent.VK_UP:this.setDir("UP");UP=true;break;case KeyEvent.VK_DOWN:this.setDir("DOWN");DOWN=true;break;case KeyEvent.VK_RIGHT:this.setDir("RIGHT");RIGHT=true;break;case KeyEvent.VK_LEFT:this.setDir("LEFT");LEFT=true;break;//打桩case KeyEvent.VK_CONTROL:Missile missile=this.fire();//将子弹扔到容器中;this.missileList.add(missile);//看看容器中有多少子弹break;

Missile类

/**
*通过构造器将buffoon开火生成的子弹参数传回给
missile类
*/public Missile(int x, int y,String missile_dir, GameClient gameClient) {this.x = x;this.y = y;//将人物的移动方向赋值给子弹this.missile_dir=missile_dir;this.width = 80;this.height = 20;this.speed = 20;this.gameClient=gameClient;}
//根据传回的方向参数给子弹一个发射方向,并在子弹超出窗口界限时,给出判断
public void move(){if(missile_dir.equals("STOP")){missile_dir="LEFT";}switch (missile_dir){case "UP":this.y -= this.speed;break;case "DOWN":this.y += this.speed;break;case "RIGHT":this.x += this.speed;break;case "LEFT":this.x -= this.speed;break;case "DR":this.x += this.speed;this.y +=this.speed;break;case "DL":this.x -= this.speed;this.y +=this.speed;break;case "UR":this.x += this.speed;this.y -=this.speed;break;case "UL":this.x -= this.speed;this.y -=this.speed;break;}if(x<190||y<40||x>800||y>420){isout=false;}}

GameClient类

 public void paint(Graphics g){g.drawImage(BG_IMAGE,0,0,DataPropertiesUtils.CLIENT_WIDTH,DataPropertiesUtils.CLIENT_HEIGHT,this);buffoon.paint(g);explode.paint(g);wall_h.paintH(g);//画子弹for (int i = 0; i < buffoon.getMissileList().size(); i++) {//           将容器中的子弹拿出来,画到屏幕上Missile missile=buffoon.getMissileList().get(i);
//根据子弹的边界判断控制子弹的运动和消失if(missile.isIsout()){missile.paint(g);missile.move();}else{//超出边界,用remove方法移除子弹对象;buffoon.getMissileList().remove(missile);}}

使用IDEA制作Java面向对象小游戏《原谅帽大作战》相关推荐

  1. Java窗体小游戏开发飞机大作战Java小游戏开发源码

    Java窗体小游戏开发飞机大作战Java小游戏开发源码

  2. java面向对象思想编写原谅帽小游戏 原谅帽游戏思路解析

    java面向对象思想编写原谅帽小游戏 原谅帽游戏思路解析: 面向对象思想 作品展示 类(游戏端)继承Frame: 首先要创建一个方法去让游戏开始和结束 使用text执行这个游戏的方法(需要有游戏标题和 ...

  3. java实现简单窗体小游戏----球球大作战

    java实现简单窗体小游戏----球球大作战 需求分析 1.分析小球的属性: ​ 坐标.大小.颜色.方向.速度 2.抽象类:Ball ​ 设计类:BallMain-创建窗体 ​ BallJPanel- ...

  4. java做小窗体_java实现简单窗体小游戏----球球大作战

    java实现简单窗体小游戏----球球大作战 需求分析 1.分析小球的属性: ​坐标.大小.颜色.方向.速度 2.抽象类:Ball ​设计类:BallMain-创建窗体 ​BallJPanel-画小球 ...

  5. 原谅帽大作战游戏程序

    原谅帽大作战 制作人:崔帅宽 时间:2020.11.10 一.如何创建原谅帽大作战的窗体: (1)先创建一个原谅帽的类包,然后创建:游戏客户端GameClinet类. /* 游戏客户端 */ publ ...

  6. egret开发HTML5小游戏-《猫猫大作战》(一)

    ps:本文适用于和我一样刚刚入门egret的同学们,大佬看到这里可以忙别的去了. 之前用egret引擎设计了一款双人设计小游戏-<疯狂大乱斗>,算是初步了解了引擎的使用,这次打算开发一款基 ...

  7. 原谅帽大作战网页版服务器连接失败,原谅帽大作战网页PC版

    当你在生活中遇到不如意,不妨来这款游戏中发泄一下,<原谅帽大作战网页版>又称绿帽大作战,十分生动形象的表现了最近网上火爆的这个梗,与其选择原谅她,给别人丢绿帽子当然爽的起飞了,游戏在线即玩 ...

  8. 【C/C++小游戏】2048 大作战!(基于Easyx图形窗口实现)

    目录 目录 目录 写在前面 游戏简介 Easyx 图形库 编写游戏 预编译代码 第一步:初始化棋盘 第二步:绘制棋盘 第三步:用户操作 第四步:封装函数 完整代码 效果展示 写在前面 大家好!本人是一 ...

  9. Java面向对象--小游戏2

    package p0721;class Player {public void happy(Game game) {game.start(); // 开机game.play(); // 开始玩游戏ga ...

最新文章

  1. MySQL 5.6--------SSL连接最佳实战
  2. delimiters 插值 选项
  3. jdk8 List集合 Stream distinct() 去重代码示例
  4. 使用入站适配器公开HTTP Restful API。 第1部分(XML)
  5. 十二、实战启动页(一)
  6. 自己动手写Docker系列 -- 4.1使用busybox创建容器
  7. 图解WebGLThree.js工作原理
  8. GLKVector3参考
  9. 清理apache日志
  10. vs2012c语言参考手册,visualstudio2012教程
  11. scrapy中文文档基础知识
  12. linux怎么用jconsole_怎么在linux jconsole
  13. 三维模型重建(1):关于三维模型重建的一些简介
  14. Python 二分法求一元三次方程唯一的正实数根
  15. 调用百度地图API去掉地图左下角的百度LOGO方法
  16. 警惕|这类人千万不要转行学IT
  17. 两轮电自2.0时代开启 小牛电动以独立主见创造新物种
  18. 北京市社会保险网上服务平台
  19. 人工智能在自动驾驶深度学习中的应用
  20. 学生计算机测评安排,计算机系学生综合测评细则

热门文章

  1. match、search、findall用法区别
  2. div中的img标签多余空白bug解决方案
  3. JVM---数据存储和访问(类文件结构)
  4. Docker学习(六):docker compose容器编排
  5. 超级实用——用word与谷歌翻译将英文PDF文档翻译成中文,免费无限制
  6. AI Studio图形化任务说明
  7. 网上收集的几个花指令
  8. 自定义博客的背景图片
  9. TensorFlow使用Keras Tuner自动调参
  10. 动态规划----最长子序列