はじめに
C言語初学者におすすめなとーっても簡単にゲームが作れるライブラリ「DXライブラリ」でAndroidゲームが作れるようになったと聞いたので触ってみたいと思います。主にwindowsアプリケーションと違う点であるタッチ機能を触っていきます。
環境: windows10, VisualStudio Community 2015
インストール
ここからダウンロード。こちらのページを参考に、新規プロジェクト作成&設定。
面倒くさそう(忘れそう)なのはソースファイルを追加する度に保存形式をShift-JISからUTF8に変えなければならない点。
さらにエミュレータの準備も必要です。実機デバッグするなら要りません。
Hello, World
とりあえず公式のサンプルコードでエミュレータでの実行ができるか試してみます。
#include "DxLib.h"
// プログラムは android_main から始まります
int android_main(void)
{
if (DxLib_Init() == -1) // DXライブラリ初期化処理
{
return -1; // エラーが起きたら直ちに終了
}
DrawBox(220, 140, 420, 340, GetColor(255, 255, 255), TRUE); // 四角形を描画する
WaitKey(); // キー入力待ち
DxLib_End(); // DXライブラリ使用の終了処理
return 0; // ソフトの終了
}
実行するとstep実行やbreakポイント等を使ったデバッグはできないという旨のダイアログが出ましたが、実行自体には成功しました。
タッチ機能を使ってみる
windowsアプリ版DXライブラリとの大きな違いは、入力がキーボードでなくタッチな点です(当たり前)
その辺の関数の動作を確認してみます。
用意されている関数は以下のたった二つ。
- GetTouchInputNum
- GetTouchInput
GetTouchInputNumはタッチされている箇所の個数を検出する関数。
GetTouchInputはタッチされている箇所の情報(XY座標)を取得します。
基本的にGetTouchInputNumでタッチIDを取得し、GetTouchInputでその座標を取得する、って流れみたいです。
Hello, Worldで表示したBoxをタッチした場所に追従させるプログラムを書いてみます。
#include "DxLib.h"
// プログラムは android_main から始まります
int android_main(void)
{
if (DxLib_Init() == -1) // DXライブラリ初期化処理
{
return -1; // エラーが起きたら直ちに終了
}
SetDrawScreen(DX_SCREEN_BACK);
int x = 220, y = 140;
while (ProcessMessage() == 0) {
ClearDrawScreen();
if (GetTouchInputNum() > 0) {
GetTouchInput(0, &x, &y);
}
DrawBox(x, y, x + 200, y + 200, GetColor(255, 255, 255), TRUE); // 四角形を描画する
ScreenFlip();
}
DxLib_End(); // DXライブラリ使用の終了処理
return 0; // ソフトの終了
}
(途中boxが途切れたりしているのは、恐らくゲームの解像度の設定等をしていないため。)
ソースコードは、DXライブラリに慣れている方にはおなじみの雰囲気ですね。
知らない人向けに簡単に説明しておくと、SetDrawScreenでダブルバッファリング用の設定で描画先を裏画面へ、whileの中がゲームのメインループで、ClearDrawScreenで画面に描画されているものの削除、ScreenFlipで裏画面を表画面に表示させています。
タッチの部分ですが、タッチ箇所が一か所以上あれば、最初に押した点をboxのxy座標にするという処理をしています。
タッチした瞬間、離した瞬間を検知する
リファレンスページを見る限りだとGetTouchInputやGetTouchInputNumしか関数がないので、タッチした瞬間や離した瞬間の検知は自前で用意しなきゃいけないのかなと思いましたが、どうやら用意されているようです。
- GetTouchInputDownLog
- GetTouchInputUpLog など
名前やヘッダの説明を読む限りだとどうやらタッチ開始時や離した時の情報のログをスタックしていて、それを取り出すことができるようです。
しかし、いろいろ試してみたものの、タッチしてもInputDownのログが取られなかったり、InputUpのログがタッチ開始時と離した時の両方でスタックされていたりと、いまいち仕様がわかりませんでした。
なので結局自前で用意してみます。
#include "DxLib.h"
// プログラムは android_main から始まります
int android_main(void)
{
if (DxLib_Init() == -1) // DXライブラリ初期化処理
{
return -1; // エラーが起きたら直ちに終了
}
SetDrawScreen(DX_SCREEN_BACK);
int x = 220, y = 140;
float ex_rate = 1.0f;
int touchbuf = 0;
while (ProcessMessage() == 0) {
ClearDrawScreen();
if (GetTouchInputNum() > 0) {
touchbuf++;
}
else {
if(touchbuf > 0)touchbuf = -1;
else touchbuf = 0;
}
if (touchbuf == 1) { // タッチした瞬間
GetTouchInput(0, &x, &y);
}
if (touchbuf == -1) { // タッチを離した瞬間
ex_rate = 1.0f;
}
if(touchbuf > 0) { // タッチしているとき
ex_rate += 0.05f;
}
DrawCircle(x, y, 50 * ex_rate, GetColor(255, 255, 255));
ScreenFlip();
}
DxLib_End(); // DXライブラリ使用の終了処理
return 0; // ソフトの終了
}
タッチした位置に円を移動させ、押し続けている間は円が大きくなり、離すと元のサイズに戻るプログラムです。
初期値0のtouchbufという変数を用意し、タッチしている間は毎フレームインクリメントします。これでtouchbufが正ならタッチされているということになり、1ならタッチした瞬間ということになります。
そしてタッチされていないときに、touchbufが正だった場合(直前フレームまでタッチされていた場合)はtouchbufの値を-1に、それ以外の場合は初期値の0に戻します。これでタッチが離された瞬間は-1の値をとります。
これでtouchbufが1か-1か正の値かでそれぞれ「タッチした瞬間か」「タッチを離した瞬間か」「タッチされているか」を判定できます。
(ちなみにこの実装方法だとタッチを離した次のフレームでタッチを行うと正しい判定ができません。人間業ではないので、気持ち悪いという人は修正してみてください)
あとがき
-
今回作成したタッチ判定は1か所しかタッチされない前提のプログラムです。必要な人は修正してください。
-
GetTouchInputLog系の関数の使い方がわかる人がいたら教えてください涙
-
途中ビルドして実行しようとすると配置エラーが発生し、エミュレータに上手くアプリがインストールされないことが何度かありました。エミュレータのタスクをすべて殺してから再起動したところ上手くいきました。
-
デバッグは実機を使うのが速くておすすめです。エミュレータは起動やアプリインストールに時間がかかってしまうので。
簡単に動くゲームが作れるので、触感はいい感じです(DXライブラリそのまんまなので当然かもしれませんが…)
Android開発に躓きがちな環境構築も簡単でした。
DXライブラリは昔からあるライブラリで、古いイメージがあるかもしれませんが、プログラミング始めたての初心者にはとてもとっつきやすいライブラリなので僕は好きです。Siv3Dなどのライブラリが台頭していますが、DXも頑張ってほしいです。(Siv3DはこっちはこっちでC++erにとっては使ってて気持ちのいい(?)ライブラリなのでおすすめですよ)