Skip to content

DingYUY/feijidazhan

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

此项目为java课程设计

本程序实现的主要功能有玩家飞机的控制、玩家飞机子弹发射、敌机移动、敌机子弹发射、boss飞机的折线运动、boss飞机的子弹发射、玩家飞机和boss飞机的血量显示、游戏的暂停开始及重新开始、控制游戏音效的播放、玩家战机的选择(五种战机)、飞机与飞机、飞机与子弹之间的碰撞。

本程序包括十一个类和一个声音文件和图片文件,其中十一个类中包括:主类(PanelFrame),里面的main方法是程序的入口;MainPanel类,功能是实现窗体主面板的界面布局,包括一个键盘监听方法;GamePanel类,是游戏的主要面板,有一个内部类(MapPanel)继承画布(Canvas)用于实现游戏地图的面板,内部类中包括paint方法绘制游戏飞机、子弹等,run方法用于启动线程,draw方法控制画布上的飞机、子弹等的变化,adapter用于键盘监听;玩家飞机类(MyPlane)、敌机类(Enemy)、子弹类(Bullet)、boss飞机类(BossPlane)都是绘制飞机、子弹等的类,其中都有绘制的方法和移动的方法以及获取坐标的方法;碰撞类(Collide),实现飞机与敌机、飞机与子弹等碰撞的判断和碰撞后的操作;Break类,包括实现玩家飞机、敌机、boss飞机爆炸的方法;Dialog类,有三个成员方法,分别描述挑战失败对话框、挑战成功对话框和设置对话框;PlaySound类,包括打开声音文件的方法(open)、建立音频行的方法(play)、暂停声音的方法(stop)、开始播放的方法(start)、回放背景音乐的方法(loop)。

程序具体实现: (1)画布的绘制的实现:本程序通过另一个线程中的循环对游戏地图画布进行重绘,循环被一个布尔型的变量isRunning控制,可用于暂停、开始、重新开始游戏功能的实现; /** * 此方法是线程run方法 */ @Override public void run() { // TODO Auto-generated method stub while(isRunning) {

            draw();//刷新界面
            try {
                Thread.sleep(20);//延时0.02s
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            time += 1;
        }
    }

(2) 玩家飞机斜飞的实现:用四个布尔型的变量记录四个方向键的状态,按下时置为true,松开是置为false,而当为true时玩家飞机进行移动; private boolean isPress01, isPress02, isPress03, isPress04; //记录按键状态 void adapter(Canvas c) {

    c.addKeyListener(new KeyAdapter() {

        @Override
        public void keyPressed(KeyEvent e) {
            // TODO Auto-generated method stub

            int key = e.getKeyCode();
            if(key == KeyEvent.VK_UP)
                isPress01 = true;

            if(key == KeyEvent.VK_DOWN)
                isPress02 = true;

            if(key == KeyEvent.VK_LEFT)
                isPress03 = true;

            if(key == KeyEvent.VK_RIGHT)
                isPress04 = true;

        }

        @Override
        public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub
            int key = e.getKeyCode();
            if(key == KeyEvent.VK_UP)
                isPress01 = false;

            if(key == KeyEvent.VK_DOWN)
                isPress02 = false;

            if(key == KeyEvent.VK_LEFT)
                isPress03 = false;

            if(key == KeyEvent.VK_RIGHT)
                isPress04 = false;
        }

    });

}

(3) 敌机的实现:敌机以一个大小为八的一维数组存储,循环出现在地图视野中,每一架敌机的初始y坐标每一次循环都是一样的,x坐标每一次都是随机的,当敌机被打到或者超过地图下方时会重置坐标; e_array = new Enemy[8];//创建敌机数组

//初始化敌机数组 for(int i = 0; i < e_array.length; i++) e_array[i] = new Enemy((-i-1)*ENEMY_SIZE-BULLET_HEIGHT);

/** * 绘制敌机方法 * @param g * @param c */ void drawEnemy(Graphics g, Canvas c, int i) { if(stayed) g.drawImage(ememyPic[i], enemy_x, enemy_y, GamePanel.ENEMY_SIZE, GamePanel.ENEMY_SIZE, c);//绘制敌机 else if(id == 0) { b = new Break(enemy_x, enemy_y); b.enemy_break(g, c, id); id++; }

    if(b != null && id != 0)
        if(id == 29){
            b.enemy_break(g, c, id);
            id = 0;
        } else {
            b.enemy_break(g, c, id);
            id++;
        }
}

(4) 玩家飞机子弹的实现:玩家飞机子弹对象用一个ArrayList存储,在固定时间间隔后绘制一个子弹对象并加入数组,当子弹超过地图时从数组中移除子弹对象; if(mp.stayed) { //创建玩家飞机子弹对象 b = new Bullet((int)(mp.getX_Y().getX())+PLANE_SIZE/2-BULLET_WIDTH/2, (int)(mp.getX_Y().getY())-BULLET_HEIGHT); b.drawBullet_1(array, gBuffer, this);//子弹绘制 for(int i = 0; i<array.size() && array.size()>1; i++) { array.get(i).drawBullet(gBuffer, this, 1);//子弹绘制 } } else if(mp.id == 30){ jb1.setEnabled(false);//设置暂停\开始按钮为不可用 isRunning = false;//设置线程不循环 new Dialog(m, 1);//打开对话框 }

(5)敌机子弹的实现:所有敌机子弹对象都是用一个ArrayList存储,但每一个子弹对象依赖于每一架敌机,在循环绘制敌机时绘制每一架敌机的子弹; //绘制敌机、敌机子弹 for(int i = 0; i < e_array.length; i++) { e_array[i].drawEnemy(gBuffer, this, i%5); if(e_array[i].stayed && e_array[i].getX_Y().getY()>0) { int t = (int)(e_array[i].getX_Y().getY())+ENEMY_SIZE; if(t < MAP_HEIGHT) { //创建敌机子弹对象 b = new Bullet((int)(e_array[i].getX_Y().getX())+ENEMY_SIZE/2-BULLET_WIDTH/2, t); b.drawBullet_2(array1, gBuffer, this, i);//子弹绘制 }

            }
            for(int j = 0; j<array1.size(); j++) {
                array1.get(j).drawBullet(gBuffer, this, 2);//子弹绘制
            }
        }

(6) Boss的实现:在一定的时间过后,敌机由于不满足if语句的时间已经超过将不再出现,而会出现boss,boss的折线运动是通过一个switch语句块实现的,由一个int类型的position变量作为运动方向的判断; /** * 绘制boss * @param g * @param c / void drawBoss(Graphics g, Canvas c) { if(stayed) g.drawImage(ima, bossPlane_x, bossPlane_y, GamePanel.BOSS_WIDTH, GamePanel.BOSS_HEIGHT, c); else if(id == 0) { b = new Break(bossPlane_x, bossPlane_y); b.boss_break(g, c, id); id++; } else { b.boss_break(g, c, id); id++; } } /* * 控制boss移动 */ void bossMove() { if(bossPlane_y < 80) bossPlane_y += step; else switch (position) {//让飞机曲线运动 case 0://向右下移 bossPlane_y += step; bossPlane_x += step; if(bossPlane_x == GamePanel.MAP_WIDTH-GamePanel.BOSS_WIDTH) position++; break; case 1://向左下移 if((point/700)%2 == 0) { bossPlane_y += 3; bossPlane_x -= step; } else { bossPlane_y += 2; bossPlane_x -= 3; } if(bossPlane_y >= GamePanel.MAP_HEIGHT-GamePanel.BOSS_HEIGHT) position++; break; case 2://向左上移 if((point/700)%2 == 0) { bossPlane_y -= step; bossPlane_x -= step; } else { bossPlane_y -= 3; bossPlane_x -= step; } if(bossPlane_x <= 0) position++; break; case 3://向右上移 bossPlane_x += step; if(bossPlane_x == 175) position = -1; break; default://向右移动 point++; if(point%300 == 0) position = 0; break; } }

(7) Boss散射子弹的实现:用大小为五的子弹数组存储boss发射的五颗发散的子弹,再用ArrayList数组存储子弹数组对象,子弹发射方向用一个switch语句块根据子弹数组的角标0~4来确定; /** * boss子弹移动方法 * @param i */ void bulletMove2(ArrayList<Bullet[]> arr, int i, int j) { if(stayed) switch (j) { case 0: bullet_x -= 2; bullet_y += 2; break; case 1: bullet_x -= 1; bullet_y += 2; break; case 2: bullet_y += 2; break; case 3: bullet_x += 1; bullet_y += 2; break; case 4: bullet_x += 2; bullet_y += 2; break; default: break; } else arr.get(i)[j] = null; }

(8) 血条的实现:玩家飞机和boss的生命用一个静态的int型变量记录,血条通过21张代表不同血量的图片根据记录生命的变量的大小绘制不同的图片,boss血条的绘制的坐标根据boss飞机的坐标确定,以保证血条在boss的上方; if(live1 >= 0 && bp.stayed) { //绘制boss对象 x = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/xue_" + ((2000-live1)/100+1) + ".png")); gBuffer.drawImage(x, (int)(bp.getX_Y().getX()), (int)(bp.getX_Y().getY()-10), 250, 10, this); }

        if(live >= 0) {
            //绘制玩家飞机对象
            x = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/xue_" + ((100-live)/5+1) + ".png"));
            gBuffer.drawImage(x, 7, 7, 200, 20, this);
        }

(9) 暂停的实现:根据isRunning为true或者false,可判断另一个线程中的循环是否进行,如果不进行,那么游戏地图将不会重绘,达到暂停效果; /** * 此方法用于执行暂停与开始 */ private void stop_start() { if(isRunning == true) { isRunning = false;//设置线程不循环 jb1.setText("开始(P)");//改变按钮文字

    } else {
        isRunning = true;//设置线程循环
        Thread d = new Thread((Runnable) jp);//创建线程
        d.start();//开启线程
        jb1.setText("暂停(P)");//改变按钮文字
    }
}

(10) 重新开始按钮的功能:当按下重新开始按钮,程序将会重新创建一个绘制地图的内部类(MapPanel)对象,同时置isRunning为false,并且还原一些参数,如:分数、血量等; jb2.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            //刷新游戏界面
            remove(jp);
            jp = new MapPanel();
            jp.setBounds(200, 0, 600, 600);
            add(jp);
            //让游戏暂停
            isRunning = false;
            jb1.setText("开始(P)");//改变按钮文字
            Bullet.before_time = System.currentTimeMillis();

            jb1.setEnabled(true);//设置暂停\开始按钮为可按
            sum = 0;//设置分数显示为0

            live = 100;//设置生命值100
            live1 = 2000;//设置boss生命值2000

            time = 0;//赋予时间

        }
    });

(11) 声音的实现:游戏声音的控制封装为一个PlaySound类,有根据传入的路径打开音频文件、建立音频行、通过调用音频行对象的start方法开始播放、通过调用音频行对象的stop方法暂停播放、通过调用音频行对象的loop方法重复播放等几个方法,当需要控制声音时调用相应方法。 /** * 打开声音文件方法 * @param s */ void open(String s) { file = new File(s);//音频文件对象 try { stream = AudioSystem.getAudioInputStream(file);//音频输入流对象 format = stream.getFormat();//音频格式对象 } catch (UnsupportedAudioFileException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }

/**
 * 建立播放音频的音频行
 */
void play() {
    info = new DataLine.Info(Clip.class, format);//音频行信息对话框
    try {
        clip = (Clip) AudioSystem.getLine(info);//音频行对话框
        clip.open(stream);//将音频数据读入音频行
    } catch (LineUnavailableException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

/**
 * 停止播放
 */
void stop() {
    clip.stop();//暂停音频播放
}

/**
 * 开始播放
 */
void start() {
    clip.start();//播放音频文件
}

/**
 * 回放背景音乐设置
 */
void loop() {
    clip.loop(20);//回放
}

}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published