Java小游戏实训——飞机大战

一、实验目的

使用Java+swing实现飞机大战小游戏

二、实验要求

1.掌握Java的基本语法。

2.掌握面向对象的编程思想。

3.掌握利用swing布局游戏界面的方法。

三、实验步骤

1.创建本次实验的文件目录结构如下:

目录结构

2.代码清单

4-1:FeiJiGame。java
package com.feiji.game;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.feiji.util.Bullet;
import com.feiji.util.GameUtil;
import com.feiji.util.Plane;
/**
* 这是游戏的主体类 需要继承Frame类
* 用户 创建游戏,
* @author Administrator
*
*/
public class FeiJiGame extends Frame{
/**
* 定义一些变量 画布 飞机 子弹
*
*/
Image bg = GameUtil.getImage("images/bg.jpg");
Plane plane = new Plane("images/plane.png",200,200);
List bulletList = new ArrayList();
//计时功能
Date starTime;
Date endTime;
Date countTime;
// 游戏状态,游戏结束时 改为false;
boolean gameState = true;
/**
* 加载游戏,画出窗口界面
*/
public void loadGame(){
//设置窗口尺寸
setSize(700,700);
//设置窗口出现横纵坐标
setLocation(200,20);
//设置窗口可见
setVisible(true);
//启动重画线程
new PaintThread().start();
//设置窗口可以关闭
addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
/**
* 加载游戏,监听按键,创建子弹数量
*/
public void launchFrame(){
loadGame();
addKeyListener(new KeyMoniter());
//启动重画线程
new PaintThread().start();
// 集合里 放进去10个子弹
for(int i=0;i<10;i++){
Bullet bullet = new Bullet();
bulletList.add(bullet);
}
starTime = new Date();
}
/**
* 往画布 上画 图像
*/
@Override
public void paint(Graphics g) {
// 画 背景图
g.drawImage(bg, 0, 0, null);// 发现 这个图像 一直在闪。怎么解决?使用缓冲技术就可以,下边的方法就是
// 画出来飞机,飞机画在背景上,飞机的位置就确定了。
plane.draw(g); // 飞机没有出来???怎么回事 live 没有 初始化
countTime = new Date();
//然后把子弹放进去,基本就可以了
if(gameState){
for(int i=0;i
Bullet b=(Bullet) bulletList.get(i);
b.draw(g);
// 循环判断 每一个子弹 是否 和 飞机 发生 重叠
// 获取子弹的 范围
Rectangle bulletRectangle = new Rectangle((int)b.x,(int)b.y,b.width,b.height);
// 获取飞机的范围
Rectangle planeRectangle = new Rectangle((int)plane.x,(int)plane.y,plane.width,plane.height);
//检测是否碰撞
boolean collide= bulletRectangle.intersects(planeRectangle);
// 如果中弹 就牺牲了。。。
if(collide){
plane.setLive(false);
endTime = new Date();
gameState = false;
}
}
}
/**
* 游戏中计时效果
*/
if(plane.isLive()){
int count_time = (int)(countTime.getTime()-starTime.getTime())/1000;
printInfo(g,"你已经坚挺了"+count_time+"秒",20,510,50);
}
/**
* 死亡时
*/
if(!plane.isLive()){
printInfo(g,"GAME OVER",80,160,200);
int survivalTime = (int)(endTime.getTime()-starTime.getTime())/1000;
printInfo(g,"生存时间:"+survivalTime+"秒",40,220,300);
switch(survivalTime/10){
case 0:
printInfo(g,"菜鸡",30,310,400);
break;
case 1:
printInfo(g,"菜鸟",30,310,400);
break;
case 2:
printInfo(g,"不错",30,310,400);
break;
case 3:
printInfo(g,"高手",30,310,400);
break;
}
}
}
/**
* 双缓冲技术,消除图像的闪烁
*/
Image ImageBuffer = null;
Graphics GraImage = null;
public void update(Graphics g){ //覆盖update方法,截取默认的调用过程
ImageBuffer = createImage(this.getWidth(), this.getHeight()); //创建图形缓冲区
GraImage = ImageBuffer.getGraphics(); //获取图形缓冲区的图形上下文
paint(GraImage); //用paint方法中编写的绘图过程对图形缓冲区绘图
GraImage.dispose(); //释放图形上下文资源
g.drawImage(ImageBuffer, 0, 0, this); //将图形缓冲区绘制到屏幕上
}
/**
* 内部类,监听 飞机的按键
* @author Administrator
*
*/
class KeyMoniter extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e) {
plane.KeyPressedControlDirection(e);
}
@Override
public void keyReleased(KeyEvent e) {
plane.KeyRelasedControlDirection(e);
}
}
/**
* 在屏幕上打印输出内容
* @param g
* @param message
* @param size
*/
public void printInfo(Graphics g,String message,int size,int x,int y){
g.setColor(Color.white);
Font f = new Font("宋体",Font.BOLD,size);
g.setFont(f);
g.drawString(message, x,y);
}
/**
* 重画窗口的线程类,是一个内部类。
* @author Administrator
*
*/
class PaintThread extends Thread {
@Override
public void run() {
while(true){
repaint();
try {
Thread.sleep(400); //1秒=1000毫秒,40毫秒表示一秒钟重画25次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 程序入口点 开始游戏
* @param args
*/
public static void main(String[] args) {
FeiJiGame game = new FeiJiGame();
// 加载游戏,游戏开始
game.launchFrame();
}
}
4-2:Bullet.java
package com.feiji.util;
import java.awt.Color;
import java.awt.Graphics;
/**
* 子弹类
* @author Administrator
*
*/
public class Bullet {
/**

* 子弹的速度 以及 发出的角度

* 坐标位置,宽度 高度

*/
double speed=10;
double degree;
public double x,y;
public int width,height;
//无参构造方法
public Bullet(){
degree = Math.random()*Math.PI*2;
x=700/2;
y=700/2;
width = 10;
height = 10;
}
/**
* 画出子弹
* @param g
*/
public void draw(Graphics g){
g.setColor(Color.green);
g.fillOval((int)x, (int)y,width, height);
x += speed*Math.cos(degree);
y += speed*Math.sin(degree);
if(x>700-width||x
degree=Math.PI-degree;
}
if(y>700-height||y
degree=-degree;
}
}
}
4-3 :GameUtil.java
package com.feiji.util;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
public class GameUtil {
/**
* 加载图片方法,传一个路径,获得路径所在的图片
* @param path
* @return
*/
public static Image getImage(String path){
URL u=GameUtil.class.getClassLoader().getResource(path);
BufferedImage img=null;
try {
img = ImageIO.read(u);
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
}
4-4 :Plane.java
package com.feiji.util;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
/**
* 飞机类
* @author Administrator
*
*/
public class Plane {
/**
* 基本属性 上下左右 宽高 是否活着
* 坐标位置
* 飞机图像
*/
boolean left,right,down,up,live;
public int x,y,width,height;
Image img ;
/*
* 画出飞机
*/
public void draw(Graphics g){
if(live){
g.drawImage(img, x, y, null);
move();
}
}
/**
* 有参构造器
* 飞机的图片地址,位置都已经确定
* 飞机的宽高 就是图片的宽高
*/
public Plane(String img_path,int x, int y){
this.img = GameUtil.getImage(img_path);
this.x = x;
this.y = y;
width = img.getWidth(null);
height = img.getWidth(null);
live = true;
}
/**
* 移动飞机,坐标改变
*/
public void move(){
if(left){
x -= 10;
}
if(up){
y -= 10;
}
if(right){
x += 10;
}
if(down){
y += 10;
}
}
/**
* 监听按键,如果 上下左右移动,就改变 变量,进行移动。
* @param e
*/
public void KeyPressedControlDirection(KeyEvent e){
int key_code = e.getKeyCode();
if(key_code == 37){
left = true;
}
if(key_code == 38){
up = true;
}
if(key_code == 39){
right = true;
}
if(key_code == 40){
down = true;
}
}
/**
* 监听是否停止按键
* @param e
*/
public void KeyRelasedControlDirection(KeyEvent e){
int key_code = e.getKeyCode();
if(key_code == 37){
left = false;
}
if(key_code == 38){
up =false;
}
if(key_code == 39){
right = false;
}
if(key_code == 40){
down = false;
}
}
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
}

五、实验结果

运行结果.gif