通过该项目让我对什么是面向对象思想有了深刻的认识,对监听器,多线程开发,缓冲区处理,锁等有了深入了解。
1.先将UI界面类构造出来
```java
public class UI {
public void initUI() {
JFrame jf = new JFrame();
jf.setSize(900, 900);
jf.setTitle("Fight");
//居中显示
jf.setLocationRelativeTo(null);
//设置退出界面的方法
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.getContentPane().setBackground(Color.WHITE);
jf.setLayout(new FlowLayout());
//设置可见
jf.setVisible(true);
ThreadlListener listener=new ThreadlListener(jf);
//给窗体添加监听器
jf.addMouseListener(listener);
//键盘监听器
jf.addKeyListener(listener);
//让窗体获取焦点
jf.requestFocus();
}
public static void main(String[] args){
UI ui = new UI() ;
ui.initUI();
}
}
可以看到上面的代码有用到监听器,所以我们接下来去写监听器类ThreadlListener.
监听器类ThreadlListener
监听器类里是比较重要的,用到了继承MouseAdapter和声明KeyListener接口,里面有线程的创建和启动,操作飞机对象的移动。
public class ThreadlListener extends MouseAdapter implements KeyListener {
private JFrame jf;//游戏界面
private Graphics g;//画笔对象
private List<Move> listBall= new ArrayList<>() ;
// private List<Plane>listBullet=new ArrayList<>();
private ThreadPlane runnable = null;//线程对象
private Plane plane;
private TimeThread timeThread; //定义任务线程
private List<Move> listbullert=new ArrayList<>();
public ThreadlListener(JFrame jf) {
this.jf = jf;
this.g = jf.getGraphics();
if(runnable == null) {
runnable = new ThreadPlane(listBall, g,listbullert);
Thread t = new Thread(runnable);
t.start();
}
}
@Override
public void keyTyped(KeyEvent e) {
System.out.println("输入");
}
@Override
public void keyPressed(KeyEvent e) {
//获取当前按键信息
int key=e.getKeyCode();
switch (key) {
case KeyEvent.VK_W:
System.out.println("W");
plane.setSpeedY(-5);
break;
case KeyEvent.VK_A:
plane.setSpeedX(-5);
break;
case KeyEvent.VK_S:
plane.setSpeedY(5);
break;
case KeyEvent.VK_D:
plane.setSpeedX(5);
break;
case KeyEvent.VK_SPACE:
System.out.println("空格");
if(timeThread == null) {
//创建我方角色对象()
plane = new Plane( 410, 750);
runnable.setPlane(plane);
//启动定时任务线程
timeThread = new TimeThread(listBall,plane,listbullert);
new Thread(timeThread).start();
break;
}
}
}
@Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
switch (key){
case KeyEvent.VK_W:
plane.setSpeedY(0);
break;
case KeyEvent.VK_A:
plane.setSpeedX(0);
break;
case KeyEvent.VK_S:
plane.setSpeedY(0);
break;
case KeyEvent.VK_D:
plane.setSpeedX(0);
break;
}
}
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
//让窗体获取焦点
jf.requestFocus();
}}
Move类为移动基础类,Plane,Bullert基础基础类来进行(构造飞机对象和绘制对象的方法)
public class Move {
private int x,y,speedX,speedY,size;
private List<Move> listBall;//!!!
private List<Move> Listbullert;
//初始化的属性
public Move(int x,int y){
this.x=x;
this.y=y;
}
public Move(){
this(400,700);
}
public Move(List<Move> listball, List<Move> listbullert) {
this.listBall = listball;
this.Listbullert = listbullert;
}
//子弹命中敌机
//绘制方法
public void drawBall(Graphics g){
g.setColor(Color.white);
g.fillOval(x,y,size,size);
}
//移动方法
public void move(){
x+=speedX;
y+=speedY;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getSpeedX() {
return speedX;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public int getSpeedY() {
return speedY;
}
public void setSpeedY(int speedY) {
this.speedY = speedY;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public List<Move> getListBall() {
return listBall;
}
public void setListBall(List<Move> listBall) {
this.listBall = listBall;
}
}
```java
public class Plane extends Move {
private Image plane,enemPlane;//用图片来表示对象
private int blood,size=100;//血条
//我的飞机对象
public Plane(int x,int y){
super(x,y);
ImageIcon image=new ImageIcon("Image/img_bg_level_5.jpg");
plane=image.getImage();
setSize(image.getIconWidth());
}
//创建敌机对象
public Plane(String path){
ImageIcon image=new ImageIcon(path);
enemPlane=image.getImage();
int x=(int)(Math.random()*800);
int y=-image.getIconHeight();
setX(x);
setY(y);
blood=10;
//移动方法
setSpeedX(0);
setSpeedY(4);
}
public void drawPlane(Graphics g){
g.drawImage(plane,getX(),getY(),100,100,null);
move();
}
public void drawEnemPlane(Graphics g){
g.drawImage(enemPlane,getX(),getY(),100,100,null);
move();
}
//绘制血条
public void drawEnemPlaneblood(Graphics g){
g.setColor(Color.red);
g.fillRect(getX(),getY(),getSize(),110);
}
@Override
public int getSize() {
return size;
}
@Override
public void setSize(int size) {
this.size = size;
}
}
## 线程类是要有的,多线程是保证该游戏能够运行的最大因素。
```java
public class ThreadPlane implements Runnable {
private List<Move> listBall;//利用遍历该数组来进行绘制图形
private List<Move>listMove;//该数组作用为保存敌机
private List<Move>ListBullert;
private Graphics g;
private boolean flag = false; //控制暂停的变量
private Plane plane;
private ImageIcon image; //游戏背景
private int x,y; //背景位置
private List<Move> listbullert;
private int size=100;
//初始化属性
public ThreadPlane(List<Move> listBall, Graphics g, List<Move> listbullert) {
this.listBall = listBall;
this.listbullert = listbullert;
this.g = g;
// this.x=x;
// this.y=y;
//初始化游戏背景
image = new ImageIcon("image/img_bg_logo.jpg");
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
//设置flag
public void setFlag(boolean flag) {
this.flag = flag;
}
public boolean getFlag() {
return flag;
}
public void setPlane(Plane plane) {
this.plane = plane;
}
@Override
public void run() {
//创建缓冲区:所有的游戏内容的绘制都必须在当前线程完成
BufferedImage buffImage = new BufferedImage(900,900,BufferedImage.TYPE_INT_RGB);
//获取缓冲区画笔
Graphics buffG = buffImage.getGraphics();
while (true) {
try {
Thread.sleep(10);
} catch (Exception interruptedException) {
interruptedException.printStackTrace();
}
if (flag) {
continue;
}
//背景图片
//背景效果
buffG.drawImage(image.getImage(),x,y,900,900,null);
// 遍历listBall
for (int i = 0; i < listBall.size(); i++) {
Plane ball = (Plane) listBall.get(i);
ball.drawEnemPlaneblood(buffG);
ball.drawEnemPlane(buffG);//作用为绘制敌机
}
for (int j=0;j<listbullert.size();j++){
Bullert bullert= (Bullert) listbullert.get(j);
bullert.drawBullert(buffG);
}
// buffG.drawImage(image.getImage(),x,y,900,900,null);
//添加条件才能够运行,只有当plane存在,才能用缓冲区画笔绘制plane对象
if (plane != null) {
//角色对象
plane.drawPlane(buffG);//暂时的目的是为了一直存在
}
coll();
//把缓冲区显示在游戏界面中
g.drawImage(buffImage,0,0,null);
}
}
public void coll() {
for (int i = 0; i < listBall.size(); i++) {
Plane enemplane = (Plane) listBall.get(i);
Plane EnemPlaneblood = (Plane) listBall.get(i);
int ax = enemplane.getX();
int ay = enemplane.getY();
for (int j = 0; j < listbullert.size(); j++) {
Bullert bullert = (Bullert) listbullert.get(j);
int bx = bullert.getX();
int by = bullert.getY();
int nDis = (int) Math.sqrt((bx - ax) * (bx - ax) + (by - ay) * (by - ay));
if (nDis <= 111) {
//血条是一个被敌机覆盖的图形,size为图形的宽
//当子弹与敌机碰撞一次,size便减少50,
EnemPlaneblood.setSize(EnemPlaneblood.getSize()-50);
listbullert.remove(j);
// listBall.remove(i);
if (EnemPlaneblood.getSize()<=0) {
//当宽度小于等于0,则进行移除
listBall.remove(i);
EnemPlaneblood.setSize(100);
break;
}
}
}
}
}}
线程自启动类实现了敌机,敌机血量,我方子弹的自动生成
public class TimeThread implements Runnable {
private long time = 3000; //间隔事件
private List<Move> listMove; //保存定时创建的敌机
private List<Move> listbullert;
private Plane myPlane;
public TimeThread(List<Move> listMove, Plane myPlane, List<Move> listbullert) {
this.listMove = listMove;
this.myPlane = myPlane;
this.listbullert = listbullert;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
String path = "Image/plane.jpg";
//创建移动对象
Plane plzane = new Plane(path);
String path1="Image/img_bg_level_5.jpg";
Bullert bullert1=new Bullert(myPlane.getX(),myPlane.getY(),path1);
listMove.add(plzane);
listbullert.add(bullert1);
}
}
}