爆発音とアニメーション

弾丸が Enemy(敵)にヒットすると爆発音を鳴らしてアニメーションします。

Java Applet の実行は、次のリンクをクリックして下さい。
爆発音とアニメーション

前田稔の超初心者のプログラム入門

プログラムの作成

  1. このページも swing の使用を止めて AWT で作成したプログラムに組み替えます。
    メモ帳などでタイプして appletshot2.java の名前で保存して下さい。
    //★ 爆発音とアニメーション    前田 稔
    //   appletviewer appletshot2.htm
    import java.applet.*;
    import java.awt.*;
    import java.io.*;
    import javax.imageio.ImageIO;
    import java.net.URL;
    import java.awt.event.*;
    import java.util.*;
    
    public class appletshot2 extends Applet implements Runnable, KeyListener
    {   // MyShip の領域
        int         key_t[] = { 0,0,0,0,0 };    //UP, RIGHT, DOWN, LEFT, SPACE
        Image       ship= null;         //Ship の画像
        int         x= 300, y= 500;     //Ship の座標
        // shot 弾丸の領域
        sprite      dangan= null;       //弾丸の切り分け
        ArrayList<shot>   list;         //弾丸の登録
        shot        shotw= new shot();  //shot のワーク
        long        nowTime,drawTime,shotTime;
        // Enemy の領域
        sprite      enemy= null;        //Enemy の画像
        // Sound &爆発の領域
        AudioClip   sound;
        sprite      bomb= null;         //爆発 の画像
        // Double Buffer
        Dimension   size;
        Image       back= null;
        Graphics    buffer;
    
        // Initialize
        public void init()
        {   //画像ロード
            ship = getImage(getDocumentBase(),"ship.png");
            dangan = new sprite(getCodeBase().toString() + "tama4.png",32,32);
            enemy = new sprite(getCodeBase().toString() + "ene5.png",80,96);
            bomb = new sprite(getCodeBase().toString() + "bomb.gif",128,128);
            sound = getAudioClip(getDocumentBase(),"14_5.wav");
            enemy.Set(0,30,40,4,0);             //Enemy の描画を開始
            enemy.SetRect(30,40,700,500);       //Enemy の枠
            setBackground(Color.gray);
            list = new ArrayList<shot>();
            shotTime= 0;
            size = getSize();
            back= createImage(size.width, size.height);
            if (back==null) System.out.print("createImage Error");
            drawTime= System.currentTimeMillis()+500;
            addKeyListener(this);
            requestFocus();
            Thread t = new Thread(this);
            t.start();
        }
    
        // Message Loop
        public void run()
        {   {   while(true)
                {   nowTime= System.currentTimeMillis();
                    if (drawTime<nowTime)
                    {   drawTime= nowTime+30;
                        action();
                        Update();
                        repaint();
                    }
                }
            }
        }
    
        // Paint
        public void paint(Graphics g)
        {   if (back==null)     return;
            buffer= back.getGraphics();
            if (buffer==null)   return;
            size = getSize();
            buffer.setColor(getBackground());
            buffer.fillRect(0, 0, size.width, size.height);
            if (ship!=null)                     // ENEMY の描画
                enemy.View(buffer);
            if (ship!=null)                     // MyShipの描画
                buffer.drawImage(ship,x,y,this);
            for(int i=0; i<list.size(); i++)    // 弾丸の描画
                dangan.View(buffer,list.get(i).Sp_no,(int)list.get(i).posX,(int)list.get(i).posY);
            if (bomb!=null)                     // 爆発の描画
                bomb.View(buffer);
            g.drawImage(back,0,0,this);
        }
    
        // 座標の更新&弾の削除
        public void Update()
        {   int i;
            enemy.Loop(10000);                  // ENEMY を切り替える
            enemy.Bound();                      // ENEMY が跳ね返る 
            for(i=0; i<list.size(); i++)        // 弾丸の座標を更新
            {   list.get(i).Update();
                if (enemy.Hit(list.get(i).posX,list.get(i).posY,50))
                {   sound.play();               // ヒットしたとき
                    bomb.Set(0,enemy.posX,enemy.posY,0,0);
                    enemy.Set(0,30,40,4,0);
                }
            }
            for(i=list.size()-1; i>=0; i--)     // 画面から出た弾丸を削除
                if (list.get(i).Sp_no==99)  list.remove(i);
            bomb.Next(200);                     // 爆発のアニメーション
        }
    
        // シップの移動
        public void action()
        {   if (key_t[0]==1)    y=y-4;  // UP
            if (key_t[1]==1)    x=x+4;  // RIGHT
            if (key_t[2]==1)    y=y+4;  // DOWN
            if (key_t[3]==1)    x=x-4;  // LEFT
            if (key_t[4]==1)            // Space で連射
            {   if (shotTime<nowTime)
                {   shotTime= nowTime+200;
                    shotw = new shot();
                    shotw.Set(1,x+20,y,0,-8);
                    list.add(shotw);
                }
            }
        }
    
        // KeyEvent Listener
        public void keyPressed(KeyEvent e)
        {   switch(e.getKeyCode( ))
            {   case KeyEvent.VK_UP :   key_t[0]= 1;  break;
                case KeyEvent.VK_RIGHT: key_t[1]= 1;  break;
                case KeyEvent.VK_DOWN : key_t[2]= 1;  break;
                case KeyEvent.VK_LEFT : key_t[3]= 1;  break;
                case KeyEvent.VK_SPACE: key_t[4]= 1;  break;
            }
        }
        public void keyReleased(KeyEvent e)
        {   switch(e.getKeyCode( ))
            {   case KeyEvent.VK_UP :   key_t[0]= 0;  break;
                case KeyEvent.VK_RIGHT: key_t[1]= 0;  break;
                case KeyEvent.VK_DOWN : key_t[2]= 0;  break;
                case KeyEvent.VK_LEFT : key_t[3]= 0;  break;
                case KeyEvent.VK_SPACE: key_t[4]= 0;  break;
            }
        }
        public void keyTyped(KeyEvent e) { }
    }
    
    //★ 画像を切り分ける class sprite は前回と同じです。
    class sprite extends Applet
    {   private Image   Img;            // Sprite Image
          ・・・
    }
    
    //★ 弾丸の座標を管理する class shot は前回と同じです。
    class shot
    {   float   posX, posY;     //弾の座標
          ・・・
    }
    
  2. Java Applet を起動する HTML ファイルです。
    <html>
    <body>
    <h3>弾丸を連射</h3>
      Applet のウインドウをクリックして Space キーを押すと弾丸を連射します。<br>
      <applet code=appletshot2.class width=800 height=600>
      </applet>
    </body>
    </html>
    
  3. インターネットブラウザを起動して HTML ファイルから実行して下さい。
    Applet のウインドウをクリックして Space キーを押すと MyShip から弾丸を連射します。
    弾丸が Enemy(敵)にヒットすると爆発音を鳴らして爆発のアニメーションを開始します。

プログラムの説明

  1. このプログラムは 自機から連射 の続きです。
    enemy はその姿を変えながら、画面上部を往復する敵の画像です。
    sound は効果音(爆発音)です。
    bomb は爆発アニメーションの領域です。
        public class appletshot2 extends JApplet implements Runnable, KeyListener
        {   // MyShip の領域
            int         key_t[] = { 0,0,0,0,0 };    //UP, RIGHT, DOWN, LEFT, SPACE
            Image       ship= null;         //Ship の画像
            int         x= 300, y= 500;     //Ship の座標
            // shot 弾丸の領域
            sprite      dangan= null;       //弾丸の切り分け
            ArrayList<shot>   list;         //弾丸の登録
            shot        shotw= new shot();  //shot のワーク
            long        nowTime,drawTime,shotTime;
            // Enemy の領域
            sprite      enemy= null;        //Enemy の画像
            // Sound &爆発の領域
            AudioClip   sound;
            sprite      bomb= null;         //爆発 の画像
        
  2. init() メソッドで初期化を行います。
    Enemy や効果音や爆発アニメーションの初期化が増えています。
    "tama4.png" は色違いの弾丸が横に4枚並んだ画像です。
    "ene5.png" は5体の Enemy が横に並んだ画像です。
    "bomb.gif" は4行4列の爆発アニメーションの画像です。
    画像を切り分けるときは sprite class を使います。
    getCodeBase() で URL を取得して、画像ファイル名(tama4.png) と結合してパラメータで渡します。
    "14_5.wav" は爆発音です。
        // Initialize
        public void init()
        {   //画像ロード
            ship = getImage(getDocumentBase(),"ship.png");
            dangan = new sprite(getCodeBase().toString() + "tama4.png",32,32);
            enemy = new sprite(getCodeBase().toString() + "ene5.png",80,96);
            bomb = new sprite(getCodeBase().toString() + "bomb.gif",128,128);
            sound = getAudioClip(getDocumentBase(),"14_5.wav");
            enemy.Set(0,30,40,4,0);             //Enemy の描画を開始
            enemy.SetRect(30,40,700,500);       //Enemy の枠
            setBackground(Color.gray);
            list = new ArrayList<shot>();
            shotTime= 0;
            size = getSize();
            back= createImage(size.width, size.height);
            if (back==null) System.out.print("createImage Error");
            drawTime= System.currentTimeMillis()+500;
            addKeyListener(this);
            requestFocus();
            Thread t = new Thread(this);
            t.start();
        }
        
  3. paint() メソッドでは背景色でクリアして、ENEMY とシップと弾丸と爆発のアニメーションを描画します。
        // Paint
        public void paint(Graphics g)
        {   if (back==null)     return;
            buffer= back.getGraphics();
            if (buffer==null)   return;
            size = getSize();
            buffer.setColor(getBackground());
            buffer.fillRect(0, 0, size.width, size.height);
            if (ship!=null)                     // ENEMY の描画
                enemy.View(buffer);
            if (ship!=null)                     // MyShipの描画
                buffer.drawImage(ship,x,y,this);
            for(int i=0; i<list.size(); i++)    // 弾丸の描画
                dangan.View(buffer,list.get(i).Sp_no,(int)list.get(i).posX,(int)list.get(i).posY);
            if (bomb!=null)                     // 爆発の描画
                bomb.View(buffer);
            g.drawImage(back,0,0,this);
        }
        
  4. ゲームの更新処理です。
    enemy.Loop(10000) でその姿を 10000ミリ秒ごとに切り替えます。
    enemy.Bound() でウインドウの枠で跳ね返ります。
    弾丸が Enemy にヒットすると爆発音を鳴らして、アニメーションを開始します。
    bomb.Next(200) で爆発アニメーションの Sprite を切り替えます。
    あとの説明は「超初心者のプログラム入門(Java2)/Game Program/シューティングゲームに挑戦」を参照して下さい。
        // 座標の更新&弾の削除
        public void Update()
        {   int i;
            enemy.Loop(10000);                  // ENEMY を切り替える
            enemy.Bound();                      // ENEMY が跳ね返る 
            for(i=0; i<list.size(); i++)        // 弾丸の座標を更新
            {   list.get(i).Update();
                if (enemy.Hit(list.get(i).posX,list.get(i).posY,50))
                {   sound.play();               // ヒットしたとき
                    bomb.Set(0,enemy.posX,enemy.posY,0,0);
                    enemy.Set(0,30,40,4,0);
                }
            }
            for(i=list.size()-1; i>=0; i--)     // 画面から出た弾丸を削除
                if (list.get(i).Sp_no==99)  list.remove(i);
            bomb.Next(200);                     // 爆発のアニメーション
        }
        
  5. ★画像を切り分ける class sprite と、弾丸の座標を管理する class shot は 自機から連射 と同じです。

Java Game Program