キーをセンス

リアルタイムにキーをセンスして画像を動かします。
Java Applet で 爆発 が楽しめます。
Windows(C++) でも キーの操作でシップを動かす を作成しています。

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

プログラムの説明

  1. シューティングゲームでは OnKeyDown() のポストを待って処理する方法は使えません。
    シューティングゲームガイド を参照して下さい。
    そこでタイマーを使って FPS(frames per second)を設定して、積極的にキーをセンスする方法を紹介します。
    OnKeyDown() を使うプログラムは キー操作で画像を移動 を参照して下さい。
    ネットで検索すると System.Windows.Input.Keyboard(Keyboard.GetKeyStates) を使う方法が紹介されていたのですが、何故か私のマシンでは効きません。 (;_;)
    仕方が無いので Win32 で愛用していた GetAsyncKeyState() を使ってプログラミングします。
  2. ソースコードです。
    @"c:\data\test\ship.png" が画像ファイルの名前です。
    /**************************************************/
    /*★ GetAsyncKeyState でキーをセンス    前田 稔 ★*/
    /**************************************************/
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    public class MyForm : Form
    {
        [DllImport("User32.dll")]
        static extern short GetAsyncKeyState(int vKey);
    
        IMAGE   App;
        int     xp,yp;
        private Timer timer1;
        private System.ComponentModel.IContainer components;
    
        // 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
            this.Width = 600;
            this.Height = 400;
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            App = new IMAGE(@"c:\data\test\ship.png");
            xp = yp = 100;
            Paint += new PaintEventHandler(MyHandler);
            timer1.Start();
        }
    
        // 画像を描画
        private void MyHandler(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            if (App.bmp == null) Application.Exit();
            App.View(g, xp, yp);
        }
    
        // タイマー割り込み
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (GetAsyncKeyState(0x1B)!=0)  Application.Exit();
            if (GetAsyncKeyState(0x25)!=0)  xp -= 2;
            if (GetAsyncKeyState(0x26)!=0)  yp -= 2;
            if (GetAsyncKeyState(0x27)!=0)  xp += 2;
            if (GetAsyncKeyState(0x28)!=0)  yp += 2;
            Invalidate();
        }
    }
    
    //☆ 画像を描画するクラス
    class IMAGE
    {
        public  Bitmap  bmp;
    
        // Constructor
        public IMAGE(string file)
        {
            try
            {   bmp= new Bitmap(file);   }
            catch
            {   MessageBox.Show("イメージが取得できません", "Error");  }
        }
    
        // 描画
        public void View(Graphics g, int x, int y)
        {
            if (bmp!=null)  g.DrawImage(bmp,x,y);
        }
    }
    
    class form01
    {
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  3. GetAsyncKeyState() 関数の宣言です。
        using System.Runtime.InteropServices;
    
        [DllImport("User32.dll")]
        static extern short GetAsyncKeyState(int vKey);
        
  4. class IMAGE の説明は キー操作で画像を移動 を参照して下さい。
    画像の「チラツキ」を押さえるために Double Buffer で描画する を使っています。
  5. タイマーの間隔を 15 ㍉秒に設定すると、毎秒 1000/15 枚のフレームが描画されます。
    マシンの能力によっては、この値を調整する必要があるかも知れません。
            timer1.Interval = 15;
            timer1.Tick += new System.EventHandler(this.timer1_Tick);
        
  6. タイマー割り込みでキーをセンスします。
            if (GetAsyncKeyState(0x1B)!=0)  Application.Exit();
            if (GetAsyncKeyState(0x25)!=0)  xp -= 2;
            if (GetAsyncKeyState(0x26)!=0)  yp -= 2;
            if (GetAsyncKeyState(0x27)!=0)  xp += 2;
            if (GetAsyncKeyState(0x28)!=0)  yp += 2;
            Invalidate();
        
  7. GetAsyncKeyState() の仕様です。
    関数が成功すると、前回の GetAsyncKeyState 関数呼び出し以降にキーが押されたかどうか、およびキーが現在押されているかどうかを示す値が返ります。
    最上位ビットがセットされたときは現在そのキーが押されていることを示し、最下位ビットがセットされたときは前回の GetAsyncKeyState 関数呼び出し以降にそのキーが押されたことを示します。
    他のスレッド( またはプロセス)のウィンドウがキーボードフォーカスを備えている場合は、0 が返ります。
    キーコードは VisualC++ の winuser.h で定義されています。
    ゲームで良く使うキーは、次のように定義されています。
        #define VK_ESCAPE         0x1B
        #define VK_SPACE          0x20
        #define VK_RETURN         0x0D
        #define VK_LEFT           0x25
        #define VK_UP             0x26
        #define VK_RIGHT          0x27
        #define VK_DOWN           0x28
        

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