iPhoneで Air 太鼓の達人を作る 3
↑これの続きです。
システム構成
(1): ToF AR が入った iOS アプリで手認識
(2): (1) からメッセージ受信、キー入力を発生させる PC プログラム
(3): 太鼓の達人 Windows 版(J key で赤ドン、K key で青カツ)
前回 (2) と (3) の間はうまく動作することが確認できました。
今回は (1) と (2) の間の確認ですが、まずは手認識を使わずにスマホタッチ操作で太鼓の達人がプレイできるかを検証したいと思います。
iPhone アプリで太鼓の達人をプレイ
結論から言うと、今回もうまく動作しました。以下が動作の様子です。
(なれない操作だったので下手くそプレイになってしまった・・・)
Wi-fi 接続でも試したのですが、その場合は若干遅延があり、快適なプレイはできませんでした。有線だと殆ど遅延は感じず、普通にゲームコントローラを使っているような気分でプレイができました。(有線って素晴らしい)
まず、PC で動作している Java プログラムについて。ソースは以下の通り。
package jp.hiehie.touchserver;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TouchServer {
public static final int PORT = 23457;
public static void main(String[] args) throws AWTException, InterruptedException, IOException {
Robot rt = new Robot();
while(true) {
ServerSocket server = null;
try {
server = new ServerSocket(PORT);
System.out.println("port binded.");
try {
Socket sock = server.accept();
System.out.println("accepted.");
BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
int i = 0;
while(i != -1) {
i = reader.read();
char c = (char)i;
System.out.println(c);
if (c == 'J') {
rt.keyPress(KeyEvent.VK_J);
rt.delay(10);
rt.keyRelease(KeyEvent.VK_J);
} else if (c == 'K') {
rt.keyPress(KeyEvent.VK_K);
rt.delay(10);
rt.keyRelease(KeyEvent.VK_K);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} finally {
if (server != null) {
server.close();
}
}
Thread.sleep(100);
}
}
}
ServerSocket を使い TCP 接続待ちをします。詳しい人に「なんで UDP じゃないの?」とツッコまれそうですが、特に理由はありません。TCP で遅延が問題無かったので良しとしています。
クライアントから送信される文字が "J" なら J キー、"K" なら K キーを押すようにしています。
続いて Unity 側のプログラム。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
public class DonKatsuClient : MonoBehaviour
{
private const int port = 23457;
private Socket sock;
private byte[] msgDon, msgKatsu;
public InputField ifIp;
public Toggle toggle;
void Start()
{
msgDon = Encoding.UTF8.GetBytes("J");
msgKatsu = Encoding.UTF8.GetBytes("K");
}
public void ToggleConnect()
{
if (toggle.isOn)
{
Connect();
}
else
{
Disconnect();
}
}
private void Connect()
{
string host = ifIp.text;
Debug.Log("Connect to " + host + ":" + port);
IPAddress ip = IPAddress.Parse(host);
sock = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
sock.NoDelay = true;
sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, false);
sock.ReceiveTimeout = 1000;
sock.SendBufferSize = 32;
IPEndPoint remoteEP = new IPEndPoint(ip, port);
sock.Connect(remoteEP);
}
private void Disconnect()
{
if (sock != null)
{
Debug.Log("Disonnect");
sock.Close();
sock = null;
}
}
public void Don()
{
if (sock != null)
{
SendReceive(msgDon);
}
}
public void Katsu()
{
if (sock != null)
{
SendReceive(msgKatsu);
}
}
private void SendReceive(byte[] msg)
{
lock (sock)
{
IAsyncResult ar = sock.BeginSend(msg, 0, msg.Length, SocketFlags.None, null, null);
sock.EndSend(ar);
}
}
}
Unity のシーンには
・TCP 接続開始のための Toggle
・赤と青の RawImage
が配置されています。
トグルをタッチ時に ToggleConnect 関数を呼ぶように Inspector 上の設定をしておきます。同様に、赤画像タッチダウンで Don 関数、青画像タッチダウンで Katsu 関数が呼ばれるようにも設定しておきます。
それぞれの関数では J と K のメッセージをサーバへ送っています。仕組みはいたって単純ですね。
ソースだけあっても困る人もいると思うので、システム全体が完成したタイミングで GitHub のソースプロジェクトを公開したいと思います。
さて、次回はいよいよ ToF AR 導入になります。はたして手認識で太鼓の達人はプレイできるのでしょうか・・・?
続きはこちら↓