まずプロジェクトですが、DXライブラリのダウンロードから、C# 用をダウンロードしてそのまま動作する場合はそれでもいいですが、Visual Studio の 2010 では動かないので普通にプロジェクトを Windows アプリケーションで作成します。
次に、bin の下の実行場所に DxLib.dll と DxLib_x64.dll と DxLibDotNet.dll をコピーして、DxLibDotNet.dll を参照すれば使えるようになります。
以下のソースコードに関しては、player.png が必要ですが、シューティングゲーム用ドット絵フリー素材よりダウンロードして作成しました。
(DxLib.dll と同じ場所に保存します)
こちらはクラス化した C# テンプレートです。プロジェクトをテンプレートで作成したら、DxLib.dll と DxLib_x64.dll と DxLibDotNet.dll と player.png をコピーして DxLibDotNet.dll を参照します
クラス化なしのベタコード
このコードで、自機が左矢印キーと右矢印キーで左右に移動します。
using DxLibDLL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DX_001 {
static class Program {
[STAThread]
static void Main() {
// ウインドウモードで起動( コメントにするとフルスクリーン )
DX.ChangeWindowMode(DX.TRUE);
// スクリーンサイズ
int screen_w = 800, screen_h = 600;
DX.SetGraphMode(screen_w, screen_h, 32);
// DXライブラリの初期化
if (DX.DxLib_Init() < 0) {
return;
}
// 描画先を裏画面に変更
DX.SetDrawScreen(DX.DX_SCREEN_BACK);
// 画像の読み込み
int player = DX.LoadGraph("player.png");
// 画像のサイズを取得
int player_graph_w, player_graph_h;
DX.GetGraphSize(player, out player_graph_w, out player_graph_h);
// プレーヤーの初期位置
int x = screen_w / 2 - player_graph_w / 2, y = screen_h - 70;
int payer_move_offset = 5;
// メインループ
while (DX.ProcessMessage() != -1) {
// ESC で終了
if (DX.CheckHitKey(DX.KEY_INPUT_ESCAPE) == 1) {
break;
}
// 右矢印キー
if (DX.CheckHitKey(DX.KEY_INPUT_RIGHT) == 1) {
x += payer_move_offset;
if (x + player_graph_w > screen_w) {
x = screen_w - player_graph_w;
}
}
// 左矢印キー
if (DX.CheckHitKey(DX.KEY_INPUT_LEFT) == 1) {
x -= payer_move_offset;
if (x < 0) {
x = 0;
}
}
// 上矢印キー
if (DX.CheckHitKey(DX.KEY_INPUT_UP) == 1) {
}
// 下矢印キー
if (DX.CheckHitKey(DX.KEY_INPUT_DOWN) == 1) {
}
// スペースキー
if (DX.CheckHitKey(DX.KEY_INPUT_SPACE) == 1) {
}
// 画面をクリア
DX.ClearDrawScreen();
// プレイヤーを描画
DX.DrawGraph(x, y, player, DX.TRUE);
// 裏画面の内容を表画面に反映する
DX.ScreenFlip();
}
// DXライブラリの後始末
DX.DxLib_End();
}
}
}
このままいろいろ機能を実装して行くと、とてもメンテしにくいコードになるので、まずゲームの本体である初期化とメインループをクラス化し、メインループ用の start メソッドの引数の無名処理を呼び出すようにしました。
Game クラスを作成して使用
static class Program {
[STAThread]
static void Main() {
// メインゲームインスタンス作成
Game game = new Game(800, 600);
// 初期化
game.init();
// 画像の読み込み
int player = DX.LoadGraph("player.png");
// 画像のサイズを取得
int player_graph_w, player_graph_h;
DX.GetGraphSize(player, out player_graph_w, out player_graph_h);
// プレーヤーの初期位置
int x = game.screen_w / 2 - player_graph_w / 2, y = game.screen_h - 70;
int payer_move_offset = 5;
game.start(
// *******************
// 主処理
// *******************
(int counter) => {
// 右矢印キー
if (DX.CheckHitKey(DX.KEY_INPUT_RIGHT) == 1) {
x += payer_move_offset;
if (x + player_graph_w > game.screen_w) {
x = game.screen_w - player_graph_w;
}
}
// 左矢印キー
if (DX.CheckHitKey(DX.KEY_INPUT_LEFT) == 1) {
x -= payer_move_offset;
if (x < 0) {
x = 0;
}
}
},
// *******************
// 描画処理
// *******************
() => {
DX.DrawGraph(x, y, player, DX.TRUE);
}
);
}
}
Game クラス
public void start(main_action call, draw_action draw) として定義されているので、内側から call と draw を呼び出して呼び出し元のコードを実行させます。
こうする事によって、ループ処理の中をキー処理と描画処理を分けて解りやすく記述できるようになります。
呼び出し元は、ラムダ式で単純なブロックを作成して記述が可能です。
class Game {
// 外部呼出し用
public delegate void main_action(int counter);
public delegate void draw_action();
// メインループカウント
private int loopCount = 0;
// スクリーンサイズ
public int screen_w;
public int screen_h;
// *******************
// コンストラクタ
// *******************
public Game(int w, int h) {
screen_w = w;
screen_h = h;
}
// *******************
// 初期化
// *******************
public void init() {
// ウインドウモードで起動( コメントにするとフルスクリーン )
DX.ChangeWindowMode(DX.TRUE);
// スクリーンサイズ
DX.SetGraphMode(screen_w, screen_h, 32);
// DXライブラリの初期化
if (DX.DxLib_Init() < 0) {
return;
}
// 描画先を裏画面に変更
DX.SetDrawScreen(DX.DX_SCREEN_BACK);
}
// *******************
// メインループ開始
// *******************
public void start(main_action call, draw_action draw) {
// メインループ
while (DX.ProcessMessage() != -1) {
// ESC で終了
if (DX.CheckHitKey(DX.KEY_INPUT_ESCAPE) == 1) {
break;
}
// 外部を呼び出し
call(loopCount);
loopCount++;
if (loopCount > 100000) {
loopCount = 0;
}
// 画面をクリア
DX.ClearDrawScreen();
// 外部を呼び出し(描画処理用)
draw();
// 裏画面の内容を表画面に反映する
DX.ScreenFlip();
}
// DXライブラリの後始末
DX.DxLib_End();
}
}
関連する記事
C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (2)