资源描述
大学课程设计飞机大战
32
2020年4月19日
文档仅供参考,不当之处,请联系改正。
湖北大学本科课程设计
题 目 Java课程设计——飞机大战
姓 名 学 号
专业年级
指导教师 职 称
12月 18日
----目录----
一. 项目介绍-------------------------------- 1
二. 概要设计
2.1资源需求------------------------------ 1
2.2游戏流程------------------------------ 1
三. 类设计
3.1游戏界面类---------------------------- 2
3.2飞行物类------------------------------ 2
3.3敌机类-------------------------------- 2
3.4蜜蜂类-------------------------------- 3
3.5玩家飞机类----------------------------- 3
3.6子弹类-------------------------------- 4
四. 编码分析
4.1游戏界面类---------------------------- 4
4.2飞行物类------------------------------ 11
4.3敌机类-------------------------------- 12
4.4蜜蜂类-------------------------------- 13
4.5玩家飞机类----------------------------- 13
4.6子弹类-------------------------------- 15
五. 游戏测试画面----------------------------- 16
六. 总结------------------------------------ 18
一.项目介绍
针对Java课程设计,我做了一个小游戏——飞机大战,游戏代码包含到本学期所学的所有知识点。
程序运行后,进入到开始画面,鼠标单击开始游戏。敌机自上向下移动,随机出现,玩家机随鼠标移动并发射子弹,消灭敌机能够获得分数,随机出现小蜜蜂,消灭后可获得奖励。
二.概要设计
2.1资源需求
此游戏需要导入图片:背景图片,开始界面,玩家飞机,敌机,小蜜蜂,子弹,暂停界面,结束界面。
显示标题界面
2.2游戏流程
单击鼠标
游戏主界面
暂停界面
鼠标移出
单击鼠标
游戏结束
玩家死亡
三.程序结构
游戏界面:
ShootGame extends JPanel
static块:导入图片
main():创立窗口
重写paint():画图
action():鼠标事件
TimerTask重写run():游戏运行的活动
飞行物类:
abstract FlyingObject
属性:x,y坐标,image,图片长宽
move():飞行物移动
outOfbound():飞行物出界
shootBy():子弹击中飞行物
敌机类:
Airplane extends FlyingObject
Int speed:移动速度
重写move()
重写outOfBound()
getScore():击中敌机后得分
Airplane():初始化敌机
蜜蜂类:
Bee extends FlyingObject
Int xSpeed,ySpeed :移动速度
Int awardType:奖励类型(双倍活力或加命)
Bee():初始化蜜蜂
重写move()
重写outOfBound()
getType():获取奖励类型
玩家飞机类:
Player extends FlyingObject
Int life,doubleFire:生命,双倍火力
Player():初始化玩家
重写move():换图片,形成飞机的动态效果
重写outOfBound()
shoot():生成子弹
moveTo():玩家机移动
isHit():玩家碰撞到飞行物
setDoubleFire():设置双倍火力
addDoubleFire():奖励双倍火力
addLife():奖励生命
deleteLife():减命
getLife():获取生命数
子弹类:
Bullet extends FlyingObject
Int speed:移动速度
Bullet():初始化子弹
重写move()
重写outOfBound()
四.编码分析
(一) ShootGame类
此类继承JPanel类构建游戏窗口并控制游戏的运行
类的成员变量:
public static final int WIDTH=400;//窗口宽
public static final int HEIGHT=600;//窗口高
//图片属性
public static BufferedImage airplane;
public static BufferedImage background;
public static BufferedImage bee;
public static BufferedImage bullet;
public static BufferedImage gameover;
public static BufferedImage player0;
public static BufferedImage player1;
public static BufferedImage pause;
public static BufferedImage start;
public static final int DOUBLE_FIRE=0;//双倍火力的属性为0
public static final int LIFE=1;//奖励生命的属性为1
public Player player=new Player();//创立玩家对象
private Bullet[] bullets={};//创立子弹对象(当前为空)
private FlyingObject[] flyings={};//创立飞行物对象(当前为空)
public static final int START=0;//状态:开始为0
public static final int RUNNING=1;//状态:运行为1
public static final int PAUSE=2;//状态:暂停为2
public static final int GAME_OVER=3;//状态:游戏结束为3
private int state=0;//当前状态
1.static块
静态块,在类加载时导入游戏所需的图片
static{
try {
airplane=ImageIO.read(ShootGame.class.getResource("airplane.png"));
background=ImageIO.read(ShootGame.class.getResource("background.png"));
bee=ImageIO.read(ShootGame.class.getResource("bee.png"));
bullet=ImageIO.read(ShootGame.class.getResource("bullet.png"));
gameover=ImageIO.read(ShootGame.class.getResource("gameover.png"));
pause=ImageIO.read(ShootGame.class.getResource("pause.png"));
start=ImageIO.read(ShootGame.class.getResource("start.png"));
player0=ImageIO.read(ShootGame.class.getResource("player0.png"));
player1=ImageIO.read(ShootGame.class.getResource("player1.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
2. main()
在main方法中创立窗口
public static void main(String[] args) {
JFrame frame=new JFrame("ShootGame");
ShootGame game=new ShootGame();
frame.add(game);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(400, 100);
frame.setAlwaysOnTop(true);
frame.setVisible(true);
frame.setSize(WIDTH, HEIGHT);
game.action();
}
3. paint()
//画图(g是画笔)
public void paint(Graphics g) {
g.drawImage(background, 0, 0, null);
paintPlayer(g);//画玩家飞机
paintFlyings(g);//画飞行物
paintBullets(g);//画子弹
paintScore(g);//画分数
paintState(g);//画游戏状态
}
//画每一个子弹
private void paintBullets(Graphics g) {
for(int i=0;i<bullets.length;i++){
Bullet b=bullets[i];
g.drawImage(b.image, b.x,b. y, null);
}
}
//画飞行物(敌机,蜜蜂)
private void paintFlyings(Graphics g) {
for (int i = 0; i < flyings.length; i++) {
FlyingObject flying=flyings[i];
g.drawImage(flying.image,flying. x,flying. y, null);
}
}
//画玩家
private void paintPlayer(Graphics g) {
g.drawImage(player.image, player.x, player.y, null);
}
//画分数
public void paintScore(Graphics g){
g.setColor(Color.RED);//设置画笔颜色为红
g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,20));//设置字体,加粗,字号
g.drawString("Score:"+score, 10, 25);
g.drawString("Life:"+player.getLife(), 10, 45);
}
//画状态
public void paintState(Graphics g){
switch(state){
case START:
g.drawImage(start, 0,0,null);break;
case PAUSE:
g.drawImage(pause, 0, 0, null);break;
case GAME_OVER:
g.drawImage(gameover, 0, 0, null);break;
}
}
4. action()
此方法处理鼠标响应事件:玩家机随鼠标移动,点击鼠标则游戏开始,鼠标移出则暂停游戏
public void action(){
MouseAdapter l=new MouseAdapter(){
//鼠标移动事件
public void mouseMoved(MouseEvent e){
if(state==RUNNING){
int x=e.getX();
int y=e.getY();
player.moveTo(x,y);
}
}
//鼠标点击事件:如果当前状态为start则开始游戏,如果当前状态为游戏结束则初始化所有对象,游戏重新开始
public void mouseClicked(MouseEvent e) {
switch(state){
case START:
state=RUNNING;
break;
case GAME_OVER:
flyings=new FlyingObject[0];
player=new Player();
bullets=new Bullet[0];
score=0;
state=START;
}
}
//鼠标移出,在当前状态为运行的情况下,改state为暂停
public void mouseExited(MouseEvent e) {
if(state==RUNNING){
state=PAUSE;
}
}
//鼠标移入,在当前状态为暂停的情况下,游戏继续运行
public void mouseEntered(MouseEvent e) {
if(state==PAUSE){
state=RUNNING;
}
}
};
this.addMouseListener(l);
this.addMouseMotionListener(l);
5. TimerTask.run()//游戏运行
private Timer timer;
private int interval=10;//时间间隔,10毫秒
int score=0;//分数
timer=new Timer();
//每隔10毫秒运行一次run方法
timer.schedule(new TimerTask() {
@Override
public void run() {
if(state==RUNNING){
enterAction();//飞行物入场(敌机或蜜蜂)
stepAction();//飞行物移动
shootAction();//射击(子弹入场)
bangAction();//碰撞
outOfBoundsAction();//删除出界对象
checkGameOverAction();//检查游戏结束
}
repaint();
}
}, interval, interval);
}
//子弹击中飞行物
public void bangAction() {
for(int i=0;i<bullets.length;i++){
if(bang(bullets[i])){
Bullet b=bullets[i];
bullets[i]=bullets[bullets.length-1];
bullets[bullets.length-1]=b;
bullets=Arrays.copyOf(bullets, bullets.length-1);
}
}
}
//判断每一个子弹和飞行物是否碰撞
public boolean bang(Bullet b){
int index=-1;//被击中的飞行物下标
for(int i=0;i<flyings.length;i++){
FlyingObject obj=flyings[i];
if(obj.shootBy(b)){
index=i;
break;
}
}
if(index!=-1){
FlyingObject obj=flyings[index];
//判断被击中的飞行物是什么类型,是敌机则得分,是蜜蜂则获得奖励
if(obj instanceof Airplane){
Airplane a=(Airplane) obj;
score+=a.getScore();
}
if(obj instanceof Bee){
Bee bee=(Bee) obj;
int type=bee.getType();
switch(type){
case DOUBLE_FIRE:
player.addDoubleFile();break;
case LIFE:
player.addLife();break;
}
}
flyings[index]=flyings[flyings.length-1];
flyings[flyings.length-1]=obj;//将击中的飞行物放到最后,并删去
flyings=Arrays.copyOf(flyings, flyings.length-1);
return true;
}else{
return false;
}
}
//删除出界飞行物
public void outOfBoundsAction(){
FlyingObject[] flyingAlive=new FlyingObject[flyings.length];
int index=0;//新数组的下标
//将未出界的飞行物放入新的数组
for (int i = 0; i < flyings.length; i++) {
if(!flyings[i].outOfBound()){
flyingAlive[index]=flyings[i];
index++;
}
}
flyings=Arrays.copyOf(flyingAlive, index);//缩小数组,将出界的飞机删除
index=0;
Bullet[] bulletAlive=new Bullet[bullets.length];
//将未出界的子弹放入新的数组
for (int i = 0; i < bullets.length; i++) {
if(!bullets[i].outOfBound()){
bulletAlive[index]=bullets[i];
index++;
}
}
bullets=Arrays.copyOf(bulletAlive, index);//缩小数组,将出界的子弹删除
}
//检查游戏是否结束
public void checkGameOverAction(){
if(isGameOver()){
state=GAME_OVER;
}
//判断游戏结束
public boolean isGameOver(){
for (int i = 0; i <flyings.length; i++) {
int index=-1;//被撞的飞行物下标
if(player.isHit(flyings[i])){
player.deleteLife();
player.setDoubleFire(0);
index=i;
}
if(index!=-1){//将被撞的飞行物从数组中删除
FlyingObject obj=flyings[index];
flyings[index]=flyings[flyings.length-1];
flyings[flyings.length-1]=obj;
flyings=Arrays.copyOf(flyings, flyings.length-1);
}
}
return player.getLife()<=0;
}
int shootIndex=0;//射击频率
//玩家发射子弹(生成子弹)
public void shootAction() {
shootIndex++;//300毫秒新建一组子弹
if(shootIndex%30==0){
Bullet[] bs=player.shoot();
//将新建的子弹加入到子弹数组中
bullets=Arrays.copyOf(bullets, bs.length+bullets.length);
System.arraycopy(bs, 0, bullets, bullets.length-bs.length, bs.length);
}
}
//子弹,玩家,飞行物走步
public void stepAction() {
for (int i = 0; i < flyings.length; i++) {
flyings[i].move();
}
for (int i = 0; i <bullets.length; i++) {
bullets[i].move();
}
player.move();
}
int flyEnteredIndex=0;//飞行物入场计数
//飞行物入场(新建对象)
public void enterAction() {
flyEnteredIndex++;//400毫秒新建一个飞行物(敌机或蜜蜂)
if(flyEnteredIndex%40==0){
FlyingObject obj=nextOne();
flyings=Arrays.copyOf(flyings, flyings.length+1);//扩容
flyings[flyings.length-1]=obj;
}
}
//工厂方法:生成对象
public static FlyingObject nextOne(){
Random rand=new Random();
int type=rand.nextInt(20);
//生成蜜蜂的概率为5%
if(type==0){
return new Bee();
}else{
return new Airplane();
}
}
(二) FlyingObject类
成员变量:
protected int x;//x坐标
protected int y;//y坐标
protected int width;//图片宽
protected int height;//图片长
protected BufferedImage image;//图片
public abstract void move();//抽象方法:飞行物移动
public abstract boolean outOfBound();//抽象方法:判断是否出界
//飞行物是否被子弹击中
public boolean shootBy(Bullet b){
int x=b.x;
int y=b.y;
return x>this.x&&x<this.x+width&&y>this.y&&y<this.y+height;
}
(三) Airplane类
成员变量:
private int speed=2;//敌机移动速度
public Airplane() {
x=(int) (Math.random()*ShootGame.WIDTH);//随机生成敌机的x坐标
y=-height;
image=ShootGame.airplane;
width=image.getWidth();
height=image.getHeight();
}
//敌机的移动方法(每次向下移动一个单位)
public void move() {
// TODO Auto-generated method stub
y+=speed;
}
//一个敌机的分数为5
public int getScore(){
return 5;
}
//判断敌机是否出界
public boolean outOfBound() {
return this.y>ShootGame.HEIGHT;
}
(四) Bee类
成员变量:
private int xSpeed=1;//蜜蜂在x轴方向的移动速度
private int ySpeed=2;//蜜蜂在y轴方向的移动速度
private int awardType;//奖励类型
public Bee() {
image=ShootGame.bee;
x=(int) (Math.random()*ShootGame.WIDTH);
y=-height;
width=image.getWidth();
height=image.getHeight();
awardType=(int) (Math.random()*2);//0或1
}
//获得奖励类型
public int getType(){
return awardType;
}
//蜜蜂移动方法
public void move() {
y+=ySpeed;
x+=xSpeed;
if(x>ShootGame.WIDTH-width){
xSpeed=-1;
}else if(x<0){
xSpeed=1;
}
}
//判断蜜蜂是否出界
public boolean outOfBound() {
return this.y>ShootGame.HEIGHT;
}
(五) Player类
成员变量:
private BufferedImage[] images;//图片数组
private int index;//换图片计数
private int life;//玩家生命
private int doubleFile;//双倍火力
public Player() {
x=150;
y=300;
image=ShootGame.player0;
width=image.getWidth();
height=image.getHeight();
images=new BufferedImage[]{ShootGame.player0,ShootGame.player1};
life=3;
doubleFile=0;
index=0;
}
//生成子弹
public Bullet[] shoot(){
if(doubleFile>0){
Bullet[] bs=new Bullet[2];
bs[0]=new Bullet(this.x+this.width/4,this.y-20);
bs[1]=new Bullet(this.x+3*this.width/4, this.y-20);
return bs;
}else{
Bullet[] bs=new Bullet[1];
bs[0]=new Bullet(this.x+width/2,this.y);
return bs;
}
}
//将玩家机移动到鼠标的位置
public void moveTo(int x,int y) {
this.x=x-this.width/2;
this.y=y-this.height/2;
}
//奖励双倍活力
public void addDoubleFile(){
doubleFile+=40;
}
//设置双倍火力的值
public void setDoubleFire(int a){
doubleFile=a;
}
//获得生命的数值
public int getLife(){
return life;
}
//减命
public void deleteLife(){
life--;
}
//奖励生命
public void addLife(){
life++;
}
//重写move方法实现玩家飞机的动态效果
public void move() {
index++;
switch((index/10)%2){
case 0:image=images[0];break;
case 1:image=images[1];break;
}
}
//重写outOfBound(),玩家飞机永不出界
public boolean outOfBound() {
return false;
}
//玩家碰撞到飞行物
public boolean isHit(FlyingObject f){
if (this.x >= f.x && this.x >= f.x + f.width) {
return false;
} else if (this.x<= f.x && this.x + this.width <= f.x) {
return false;
} else if (this.y >= f.y && this.y >= f.y + f.height) {
return false;
} else if (this.y <= f.y && this.y + this.height <= f.y) {
return false;
}
return true;
}
(六) Bullet类
成员变量:
private int speed=3;//子弹的移动速度
public Bullet(int x,int y) {
this.x=x;
this.y=y;
image=ShootGame.bullet;
width=image.getWidth();
height=image.getHeight();
}
//重写move方法,子弹每次向上移动3个单位
public void move() {
y-=speed;
}
//判断子弹是否出界
public boolean outOfBound() {
// TODO Auto-generated method stub
return this.y<-height;
}
五.游戏测试
游戏开始:
游戏运行中:
游戏暂停:
游戏结束:
六.总结
此次完成的小游戏还有很多改进的地方,比如能够加入背景音乐,在子弹击中飞行物后有一个飞机爆炸的效果,飞行物的移动轨迹能够设计的更复杂一些,游戏结束后能够增加一个统计分数的界面等等。
在这次课程设计中,我学到了很多。在写代码的时候碰到了许多问题,比如在设计类的时候总是会遗漏一些方法,总要在使用时才补上该方法。另外也学到一些课本外的知识,如点与矩形,矩形与矩形的碰撞分析。在初步完成后,运行代码时还出现了,子弹击中飞行物后子弹不会消失的问题。这次的课程设计让我发现实践的重要性,学到的知识在多次运用后才能融汇贯通。
湖北大学本科课程设计成绩评定表
项目
权重
分值
具体要求
得分
文献阅读与调查论证
0.20
100
能独立查阅文献和从事其它调研;有收集、加工各种信息的能力
论文撰写质量
0.40
100
设计合理、理论分析与计算正确,实验数据准确可靠;有较强的实际动手能力、经济分析能力和计算机应用能力;设计说明书完全符合规范化要求,用A4复印纸打印成文
学习态度
0.30
100
学习态度认真,科学作风严谨,严格按要求开展各项工作,按期完成任务
学术水平与创新
0.10
100
设计有创意,有一定的学
展开阅读全文