一、功能:
1、实现键盘控制飞机超八个方向移动 2、碰撞事件 3、双缓冲技术消除屏幕闪烁问题 4、游戏等级的判断等等
二、特点:1、本代码的结构合理清晰,重构得好(所以你会看到较多的包和工具类) 2、增加了必要的代码注释
三、最终效果
四、package和class的关系图
五、代码部分:
1、Constants类
package com.liang.util;
public class Constants {
public static final double FRAME_WIDTH = 400;
public static final double FRAME_HEIGTH = 600;
}
2、获取图片的工具类
package com.liang.util;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
//工具类:获取图片
public class GameUtil {
public static Image getImage(String imagepath){
URL url = GameUtil.class.getClassLoader().getResource(imagepath);
BufferedImage image = null;
try{
image = ImageIO.read(url);
}catch(Exception e){
e.printStackTrace();
}
return image;
}
}
3、JFrame父类
package com.liang.util;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class MyFrame extends JFrame{
/**
* 工具类:框架
*/
private static final long serialVersionUID = 1L;
public void launchFrame(){
this.setBounds(200, 100, (int)Constants.FRAME_WIDTH, (int)Constants.FRAME_HEIGTH);
this.setVisible(true);
this.setResizable(false);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});
new PaintThread().start();
}
/*//利用双缓冲处理闪烁问题
private Image offScreenImage = null;
private Graphics goff = null;
@Override
public void update(Graphics g) {
//super.update(g);
if(offScreenImage == null){
offScreenImage = this.createImage((int)Constants.FRAME_WIDTH, (int)Constants.FRAME_HEIGTH);
goff = offScreenImage.getGraphics();
paint(goff);//自己调用这个函数
g.drawImage(offScreenImage, 0, 0, null);
}
}*/
//内部类,线程
public class PaintThread extends Thread{
@Override
public void run() {
while(true){
try{
repaint();
Thread.sleep(33);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
4、Bullet类
package com.liang.planeGame; import java.awt.Color; import java.awt.Graphics; import com.liang.util.Constants; public class Bullet extends Substance{ //image, body_x, body_y,speed,degree //private Image image; private double degree; public Bullet(){ } public Bullet(double x,double y,double speed, double width, double height){ super(); //this.image = image; this.x = x; this.y = y; this.speed = speed; degree = Math.random()*Math.PI * 2; this.width = width; this.height = height; } public void draw(Graphics g){ //g.drawImage(image, (int)x, (int)y, null); Color c = g.getColor(); g.setColor(Color.yellow); g.fillOval((int)x, (int)y, (int)width, (int)height); g.setColor(c); move(); } private void move(){ x += speed * Math.cos(degree); y += speed * Math.sin(degree); if(x < 0 || x > Constants.FRAME_WIDTH){ degree = Math.PI - degree; } if(y < 0 || y > Constants.FRAME_HEIGTH){ degree = -degree; } } }
5、plane类
package com.liang.planeGame; import java.awt.Graphics; import java.awt.Image; import com.liang.util.GameUtil; public class Plane extends Substance{ //判断键盘的方向 private boolean left, right , up, down; private boolean alive = true; //飞机是否被击中 public Plane(){ } public Plane(Image image){ this.image = image; } public Plane(String imagePath){ this.image = GameUtil.getImage(imagePath); } public Plane(String imagePath,double x, double y, double speed) { super(); this.image = GameUtil.getImage(imagePath); this.x = x; this.y = y; this.speed = speed; this.width = image.getWidth(null); this.height = image.getWidth(null); } public void draw(Graphics g){ if(alive){ g.drawImage(image, (int)x, (int)y, null); move(); } } private void move(){ if(left){ x -= speed; } if(right){ x += speed; } if(up){ y -= speed; } if(down){ y += speed; } } public boolean isAlive() { return alive; } public void setAlive(boolean alive) { this.alive = alive; } public boolean isLeft() { return left; } public void setLeft(boolean left) { this.left = left; } public boolean isRight() { return right; } public void setRight(boolean right) { this.right = right; } public boolean isDown() { return down; } public void setDown(boolean down) { this.down = down; } public boolean isUp() { return up; } public void setUp(boolean up) { this.up = up; } }
6、框架父类
package com.liang.planeGame; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Image; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Date; import com.liang.util.Constants; import com.liang.util.GameUtil; import com.liang.util.MyFrame; public class GameFrame extends MyFrame{ /** * */ private static final long serialVersionUID = 1L; Image bg = GameUtil.getImage("Images/background.jpg"); Plane plane = new Plane("Images/plane.PNG",200, 200, 4);//image, 初始化x和y,speed ArrayList<Bullet> bulletList = new ArrayList<Bullet>(); Date startTime; Date endTime; int count = 0;//防止计时数改变 //String rankInfo; @Override public void paint(Graphics g) { g.drawImage(bg, 0, 0, null); plane.draw(g); //draw bullets for(int i = 0; i < bulletList.size(); i++){ Bullet b = (Bullet)bulletList.get(i); if(plane.isAlive() == true){ b.draw(g); } boolean hit = b.getRect().intersects(plane.getRect()); if(hit){ plane.setAlive(false); //防止再次碰到,导致计时数改变 if(count == 0){ endTime = new Date(); count++; } } } if(! plane.isAlive()){ paintInfo(g, " GameOver", 70,260,32,Color.yellow); paintInfo(g, "key ENTER to again", 65, 60, 23, Color.white); //计时 long time = (endTime.getTime() - startTime.getTime())/1000; // 时间 paintInfo(g, time+" seccond", 290, 60, 20, Color.orange); //等级信息 String rankInformation = Ranking(time); paintInfo(g, rankInformation, 130, 300, 34, Color.white); } } public void paintInfo(Graphics g, String string, double x, double y, int word_size, Color color){ Font font = new Font("正楷",Font.BOLD, word_size); Color c = g.getColor(); g.setColor(color); g.setFont(font); g.drawString(string, (int)x, (int)y); g.setColor(c); } //等级 public String Ranking(long time){ String rankInfo = null; switch((int)time/10){ case 0: case 1: rankInfo = "菜鸟"; break; case 2: rankInfo = "小鸟"; break; case 3: rankInfo = "大鸟"; break; case 4: rankInfo = "鸟人"; break; default:rankInfo = "凤凰"; } return rankInfo; } //内部类,键盘事件 public class MyKeyEvent extends KeyAdapter{ @Override public void keyPressed(KeyEvent event) { switch(event.getKeyCode()){ case KeyEvent.VK_LEFT: plane.setLeft(true); break; case KeyEvent.VK_RIGHT: plane.setRight(true); break; case KeyEvent.VK_UP: plane.setUp(true); break; case KeyEvent.VK_DOWN: plane.setDown(true); break; default: } } @Override public void keyReleased(KeyEvent event) { switch(event.getKeyCode()){ case KeyEvent.VK_LEFT: plane.setLeft(false); break; case KeyEvent.VK_RIGHT: plane.setRight(false); break; case KeyEvent.VK_UP: plane.setUp(false); break; case KeyEvent.VK_DOWN: plane.setDown(false); break; default: } } } //重写父类的方法,以便加入监听器 @Override public void launchFrame() { super.launchFrame(); startTime = new Date(); addKeyListener(new MyKeyEvent()); //增加子弹对象 for(int i = 0; i < 20; i++){ Bullet bullet = new Bullet(Constants.FRAME_WIDTH/2, 20, 3, 10, 10);//x, y, speed bulletList.add(bullet); //bullet.get(i).draw(g); } } public static void main(String args[]){ new GameFrame().launchFrame(); } }
7、bullet和plane的父类
package com.liang.planeGame; import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; public class Substance { //image, body_x, body_y,speech, Image image; protected double x , y , speed; protected double width, height;//the width and height of image //空构造方法 public Substance(){ } public Substance(Image image, double x, double y, double speed, double width, double height) { super(); this.image = image; this.x = x; this.y = y; this.speed = speed; this.width = width; this.height = height; } public void draw(Graphics g){ g.drawImage(image, (int)x, (int)y, null); } //绘制飞机图片所在的长方形,以便进行碰撞事件的判断 public Rectangle getRect(){ return new Rectangle((int)x, (int)y, (int)width, (int)height); } }