WinfowsFormアプリでキャラクタをスムーズに移動させる
通常、キー入力はリピート間隔が設定されているため、キーを押しっぱなしの場合、1回目の入力と2回目以降の入力の間、若干のウェイトがあります。タイプ入力の場合、必要な機能なのですがゲームではゲーム性を損なうためこの機能は使いたくありません。WindowsOSの設定変更、レジストリの変更等では、他のアプリへの影響が考えられるため、プログラムで対処します。
目次
基本のサンプル
Form画面にLabelコンポーネント(label1)をD&Dしておきます。
using System;
using System.Windows.Forms;
namespace RealInputSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
label1.Text = "☆彡";
//timerイベント
var update = new Timer();
// Updateイベントハンドラを呼び出す(「Update」は独自名)
update.Tick += new EventHandler(Update);
// 16ms毎
update.Interval = 16;
// タイマースタート
update.Start();
}
private void Update(object sender, EventArgs e)
{
MoveChar();
}
private void MoveChar()
{
if (Input.KeyPress(Keys.Right)) label1.Left += 1;
if (Input.KeyPress(Keys.Left)) label1.Left -= 1;
if (Input.KeyPress(Keys.Up)) label1.Top -= 1;
if (Input.KeyPress(Keys.Down)) label1.Top += 1;
}
}
// キー入力クラス
static class Input
{
// DLLのインポート
[System.Runtime.InteropServices.DllImport("user32.dll")]
// externで宣言が必要
private static extern short GetKeyState(int nVirtKey);
// 最上位Bitが1で KeyDownを取得
public static bool KeyPress(Keys keyCode) => (GetKeyState((int)keyCode) & 0x8000) > 0;
}
}
WindowsFormアプリサンプル
実行結果
Form1クラス(プログラム作成)
using System;
using System.Drawing;
using System.Windows.Forms;
namespace RealInputSample
{
public partial class Form1 : Form
{
// プレイヤー変数の宣言
Player player;
// 猫のイメージ
readonly Image CatImage = Properties.Resources.Cat;
// 犬のイメージ
readonly Image DogImage = Properties.Resources.Dog;
public Form1()
{
InitializeComponent();
//timerイベント
var update = new Timer();
// Updateイベントハンドラを呼び出す(「Update」は独自名)
update.Tick += new EventHandler(Update);
// 16ms毎
update.Interval = 16;
// タイマースタート
update.Start();
}
// 60fps(16ms毎)でコールされるタイマーイベント
void Update(object sender, EventArgs e)
{
// 移動
if (Input.KeyPress(Keys.Right)) player.Left += 1;
if (Input.KeyPress(Keys.Left)) player.Left -= 1;
if (Input.KeyPress(Keys.Up)) player.Top -= 1;
if (Input.KeyPress(Keys.Down)) player.Top += 1;
// 猫画像に切り替え
if (Input.KeyDown(Keys.C))
{
player.Image = CatImage;
}
// 犬画像に切り替え
if (Input.KeyDown(Keys.D))
{
player.Image = DogImage;
}
}
// フォームがロードされた時、一度だけ呼び出される
void Form1_Load(object sender, EventArgs e)
{
// プレイヤーのインスタンス化
// インスタンス作成の時にリソースに登録したDogイメージをセット
player = new Player(DogImage);
// 現在のフォームコントロールに追加
Controls.Add(player);
}
}
}
VisualStudioによって作成押されたForm1クラス(自動作成のため更新しないこと)
確認用
namespace RealInputSample
{
partial class Form1
{
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(13F, 24F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
}
}
Inputクラス
using System.Windows.Forms;
namespace RealInputSample
{
/// <summary>
/// キー入力クラス
/// </summary>
static class Input
{
// DLLのインポート
[System.Runtime.InteropServices.DllImport("user32.dll")]
// externで宣言が必要
static extern short GetKeyState(int nVirtKey);
// 最上位Bitが1で KeyDownを取得
/// <summary>
/// キーが押されているかを判定
/// </summary>
/// <param name="keyCode">入力キーコード</param>
/// <returns>キーが押されているとtrue</returns>
public static bool KeyPress(Keys keyCode)
{
return (GetKeyState((int)keyCode) & 0x8000) > 0;
}
public static bool IsKeyTrigger { get; private set; }
/// <summary>
/// キーが押された時の判定
/// </summary>
/// <param name="keyCode">入力キーコード</param>
/// <returns>キーが押された瞬間一度だけtrue</returns>
public static bool KeyDown(Keys keyCode)
{
if (!((GetKeyState((int)keyCode) & 0x8000) > 0))
{
return IsKeyTrigger = false;
}
if (!IsKeyTrigger)
{
return IsKeyTrigger = true;
}
return false;
}
/// <summary>
/// キーが押されて、離されたか判定
/// </summary>
/// <param name="keyCode">入力キーコード</param>
/// <returns>キーが離された瞬間一度だけtrue</returns>
public static bool KeyUp(Keys keyCode)
{
if ((GetKeyState((int)keyCode) & 0x8000) > 0)
return false;
if (IsKeyTrigger)
{
return !(IsKeyTrigger = false);
}
return false;
}
}
}
Playerクラス
using System.Drawing;
using System.Windows.Forms;
namespace RealInputSample
{
/// <summary>
/// イメージを含むプレイヤークラス
/// PictureBoxを使えるように継承している
/// </summary>
class Player : PictureBox
{
/// <summary>
/// ダミー
/// </summary>
public int HP { get; set; }
/// <summary>
/// ダミー
/// </summary>
public int MP { get; set; }
/// <summary>
/// プレイヤーインスタンスの作成
/// </summary>
/// <param name="image">PictureBoxにセットするイメージ</param>
public Player(Image image)
{
// 位置
Location = new Point(100, 100);
// 大きさ
Size = new Size(50, 50);
// イメージ
Image = image;
// ストレッチ設定
SizeMode = PictureBoxSizeMode.StretchImage;
}
}
}
ディスカッション
コメント一覧
まだ、コメントがありません