敵に向かって連射

弾丸を敵に向かって連射します。
Java でも 爆発音と爆発のアニメーション を作成しています。

前田稔(Maeda Minoru)の超初心者のプログラム入門

敵に向かって連射

  1. SHOOT Class と ANIME Class を利用して、弾丸を敵に向かって連射します。
    @"c:\data\test\tama4.png",32,32 は、色違いの4個の弾丸が並んだ画像です。

    @"c:\data\test\Ene5.png",80,96 は、5体の Enemy が並んだ画像です。
    画像は ENEMY(敵)が出現 から取得して下さい。
    /*★ Enemy に向かって連射    前田 稔 ★*/
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Collections;
    using System.Runtime.InteropServices;
    
    public class MyForm : Form
    {
        [DllImport("User32.dll")]
        static extern short GetAsyncKeyState(int vKey);
    
        SHOOT   Shoot;      //弾丸を一括管理するクラス
        ANIME   Enemy;      //アニメーションクラス
        private Timer timer1;
        private System.ComponentModel.IContainer components;
        Rectangle rect1 = new Rectangle(20,20,500,380);
        Rectangle rect2 = new Rectangle(20,20,540,380);
        int     cnt;        //弾丸の連射間隔を設定
    
        // Constructor
        public MyForm()
        {
            // timer1
            components = new System.ComponentModel.Container();
            timer1 = new System.Windows.Forms.Timer(this.components);
            SuspendLayout();
            timer1.Interval = 15;
            timer1.Tick += new System.EventHandler(this.timer1_Tick);
            // MyForm
            BackColor = SystemColors.AppWorkspace;
            this.Width = 640;
            this.Height = 480;
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            Shoot = new SHOOT(@"c:\data\test\tama4.png",32,32);
            Enemy = new ANIME(@"c:\data\test\Ene5.png",80,96);
            Enemy.Set(0,50,10,2,0);
            Paint += new PaintEventHandler(MyHandler);
            timer1.Start();
        }
    
        // 画像を描画
        private void MyHandler(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            if (Enemy.Bmp == null)  Application.Exit();
            Enemy.View(g);
            Shoot.View(g);
        }
    
        // タイマー割り込み
        private void timer1_Tick(object sender, EventArgs e)
        {
            short   kw;
            if (GetAsyncKeyState(0x1B)!=0)  Application.Exit();
            cnt++;
            Shoot.Move(rect2);
            kw = GetAsyncKeyState(0x20);    //空白
            if (kw!=0 && cnt>30)
            {
                Shoot.Add(0, 300, 400, 0, -1.5f);
                cnt = 0;
            }
            Enemy.Loop(60000000);
            Enemy.Bound(rect1);
            Invalidate();
        }
    }
    
    //☆ 弾丸を一括管理するクラス
    public class SHOOT
    {
        //★「 弾丸を一括管理」のページを参照してください。
    }
    
    //☆ アニメーションクラス
    class ANIME
    {
        //★「アニメーションクラス」のページを参照してください。
    }
    
    class form01
    {
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  2. SHOOT Shoot; は、弾丸を一括管理するクラスの定義です。
    ANIME Enemy; は、Enemy の画像を順番に切り替えながら画面上部で往復するクラスです。
    Rectangle rect1 は、Enemy の描画範囲で、枠に当たると方向が反転します。
    Rectangle rect2 は、弾丸の描画範囲で、枠を超えると弾丸を削除します。
        SHOOT   Shoot;      //弾丸を一括管理するクラス
        ANIME   Enemy;      //アニメーションクラス
        Rectangle rect1 = new Rectangle(20,20,500,380);
        Rectangle rect2 = new Rectangle(20,20,540,380);
        
  3. MyForm の Constructor で SHOOT と ANIME をインスタンス化します。
    Enemy.Set(0,50,10,2,0); で Enemy の描画を開始します。
            Shoot = new SHOOT(@"c:\data\test\tama4.png",32,32);
            Enemy = new ANIME(@"c:\data\test\Ene5.png",80,96);
            Enemy.Set(0,50,10,2,0);
            Paint += new PaintEventHandler(MyHandler);
            timer1.Start();
        
  4. 画像を描画する MyHandler() メソッドです。
    Enemy.View(g); で Enemy を、Shoot.View(g); で弾丸を描画します。
        // 画像を描画
        private void MyHandler(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            if (Enemy.Bmp == null)  Application.Exit();
            Enemy.View(g);
            Shoot.View(g);
        }
        
  5. タイマー割り込みで起動する timer1_Tick メソッドです。
    cnt++; は適当な間隔を置いて弾丸を連射するためのカウントです。
    Shoot.Move(rect2); で弾丸を移動します。
    空白キー(0x20)を検出して、弾丸を連射します。
    Enemy.Loop(60000000); で 60000000 ごとに Enemy の画像を切り替えます。
    Enemy.Bound(rect1); で Enemy が枠に当たると方向が反転します。
        private void timer1_Tick(object sender, EventArgs e)
        {
            short   kw;
            if (GetAsyncKeyState(0x1B)!=0)  Application.Exit();
            cnt++;
            Shoot.Move(rect2);
            kw = GetAsyncKeyState(0x20);    //空白
            if (kw!=0 && cnt>30)
            {
                Shoot.Add(0, 300, 400, 0, -1.5f);
                cnt = 0;
            }
            Enemy.Loop(60000000);
            Enemy.Bound(rect1);
            Invalidate();
        }
        

当り判定と爆発

  1. 自機から敵に向かって弾丸を発射して、当たると爆発します。
    @"c:\data\test\tama4.png",32,32 は、色違いの4個の弾丸が並んだ画像です。
    @"c:\data\test\Ene5.png",80,96 は、5体の Enemy が並んだ画像です。
    @"c:\data\test\ship.png" は自機の画像です。
    @"c:\data\test\Bomb.gif",128,128 は爆発アニメーションの画像です。
    @"c:\data\test\bomb.wav" は爆発の音です。
    /*********************************/
    /*★ 当り判定と爆発    前田 稔 ★*/
    /*********************************/
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Collections;
    using System.Runtime.InteropServices;
    
    public class MyForm : Form
    {
        [DllImport("User32.dll")]
        static extern short GetAsyncKeyState(int vKey);
    
        IMAGE   Ship;       //シップを描画するクラス
        SHOOT   Shoot;      //弾丸を一括管理するクラス
        ANIME   Enemy;      //Enemy を描画するクラス
        ANIME   Bomb;       //爆発アニメーション
        private Timer timer1;
        private System.ComponentModel.IContainer components;
        Rectangle rect1 = new Rectangle(20,20,500,380);
        Rectangle rect2 = new Rectangle(20,20,540,380);
        int     xp,yp;      //シップの座標
        int     cnt;        //弾丸の連射間隔を設定
        System.Media.SoundPlayer player;
    
        // Constructor
        public MyForm()
        {
            // timer1
            components = new System.ComponentModel.Container();
            timer1 = new System.Windows.Forms.Timer(this.components);
            SuspendLayout();
            timer1.Interval = 15;
            timer1.Tick += new System.EventHandler(this.timer1_Tick);
            // MyForm
            BackColor = SystemColors.AppWorkspace;
            this.Width = 640;
            this.Height = 480;
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            Ship = new IMAGE(@"c:\data\test\ship.png");
            xp = 300;
            yp = 360;
            Shoot = new SHOOT(@"c:\data\test\tama4.png",32,32);
            Enemy = new ANIME(@"c:\data\test\Ene5.png",80,96);
            Enemy.Set(0,50,10,2,0);
            Bomb = new ANIME(@"c:\data\test\Bomb.gif",128,128);
            player = new System.Media.SoundPlayer(@"c:\data\test\bomb.wav");
            Paint += new PaintEventHandler(MyHandler);
            timer1.Start();
        }
    
        // 画像を描画
        private void MyHandler(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            if (Enemy.Bmp == null)  Application.Exit();
            Ship.View(g, xp, yp);
            Enemy.View(g);
            Shoot.View(g);
            Bomb.View(g);
        }
    
        // タイマー割り込み
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (GetAsyncKeyState(0x1B)!=0)  Application.Exit();
            cnt++;
            Shoot.Move(rect2);
    
            // 弾丸と Enemy との当り判定
            if (Shoot.Hit(Enemy.X,Enemy.Y,50))
            {   //ヒットしたとき
                player.Play();
                Bomb.Set(0,Enemy.X,Enemy.Y);
                Enemy.Set(0,50,10,2,0); //Enemy を左端に移動
            }
            if (GetAsyncKeyState(0x25)!=0)  xp -= 2;
            if (GetAsyncKeyState(0x26)!=0)  yp -= 2;
            if (GetAsyncKeyState(0x27)!=0)  xp += 2;
            if (GetAsyncKeyState(0x28)!=0)  yp += 2;
            if (GetAsyncKeyState(0x20)!=0 && cnt>30)
            {
                Shoot.Add(0, xp + 20, yp, 0, -1.5f);
                cnt = 0;
            }
            Bomb.Next(1000000);
            Enemy.Loop(60000000);
            Enemy.Bound(rect1);
            Invalidate();
        }
    }
    
    //☆ 画像を描画するクラス
    class IMAGE
    {
        //★「 画像を描画するクラス」のページを参照してください。
    }
    
    //☆ 弾丸を一括管理するクラス
    public class SHOOT
    {
        //★「 弾丸を一括管理」のページを参照してください。
    }
    
    //☆ アニメーションクラス
    class ANIME
    {
        //★「アニメーションクラス」のページを参照してください。
    }
    
    class form01
    {
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  2. IMAGE Ship; は、自機画像を描画するクラスの定義です。
    SHOOT Shoot; は、弾丸を一括管理するクラスの定義です。
    ANIME Enemy; は、Enemy の画像を順番に切り替えながら画面上部で往復するクラスです。
    ANIME Bomb; は、爆発のアニメーションをするクラスの定義です。
        IMAGE   Ship;       //シップを描画するクラス
        SHOOT   Shoot;      //弾丸を一括管理するクラス
        ANIME   Enemy;      //Enemy を描画するクラス
        ANIME   Bomb;       //爆発アニメーション
        
  3. 画像を描画する MyHandler() メソッドです。
    Ship.View(g, xp, yp); で自機を、Enemy.View(g); で Enemy を、Shoot.View(g); で弾丸を、Bomb.View(g); で爆発アニメーションを描画します。
        private void MyHandler(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            if (Enemy.Bmp == null)  Application.Exit();
            Ship.View(g, xp, yp);
            Enemy.View(g);
            Shoot.View(g);
            Bomb.View(g);
        }
        
  4. タイマー割り込みで起動する timer1_Tick メソッドです。
    Shoot.Move(rect2); で弾丸を移動します。
    Shoot.Hit(Enemy.X,Enemy.Y,50) で Enemy と弾丸の当たり判定をします。
    Enemy.X,Enemy.Y が Enemy の座標で、50 は当たり判定の直線距離です。
    この値は実際にプレイして決めて下さい。
    ヒットすると、爆発音を鳴らして、爆発アニメーションを開始します。
    上下左右のキーで自機を操作します。
    空白キー(0x20)を検出して、弾丸を連射します。
    Bomb.Next(1000000); で爆発アニメーションの画像を切り替えます。
    Enemy.Loop(60000000); で 60000000 ごとに Enemy の画像を切り替えます。
    Enemy.Bound(rect1); で Enemy が枠に当たると方向が反転します。
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (GetAsyncKeyState(0x1B)!=0)  Application.Exit();
            cnt++;
            Shoot.Move(rect2);
    
            // 弾丸と Enemy との当り判定
            if (Shoot.Hit(Enemy.X,Enemy.Y,50))
            {   //ヒットしたとき
                player.Play();
                Bomb.Set(0,Enemy.X,Enemy.Y);
                Enemy.Set(0,50,10,2,0); //Enemy を左端に移動
            }
            if (GetAsyncKeyState(0x25)!=0)  xp -= 2;
            if (GetAsyncKeyState(0x26)!=0)  yp -= 2;
            if (GetAsyncKeyState(0x27)!=0)  xp += 2;
            if (GetAsyncKeyState(0x28)!=0)  yp += 2;
            if (GetAsyncKeyState(0x20)!=0 && cnt>30)
            {
                Shoot.Add(0, xp + 20, yp, 0, -1.5f);
                cnt = 0;
            }
            Bomb.Next(1000000);
            Enemy.Loop(60000000);
            Enemy.Bound(rect1);
            Invalidate();
        }
        
  5. Java Applet でも 爆発 を作成しています。
    プログラムを動かすにはクライアント側に Java Applet の動作環境の設定が必要です。

前田稔(Maeda Minoru)の超初心者のプログラム入門