ZIG SIM × Processing|スマホをゲームコントローラにしよう!
まとめると
・ZIG SIMというアプリをスマホに入れるだけでスマホから加速度センサ・ジャイロセンサ・GPSなどのデータを取得できる
・UDP/TCP通信でProcessingにデータを送れる
・Processingへの送信の仕方(コードの書き方)と取得できるセンサ一覧をまとめた
・ZIG SIMでコントローラを自作して、Processingで作ったゲームと組み合わせてみた
はじめに
こちらはProcessing Advent Calender 2021の2日目の記事です(参加4年目).
今回はゲーム制作でお世話になっているZIG SIMを紹介します.電子工作がめんどくさいときやお財布の事情で電子部品を買いたくないとき使っています.
ちなみにZIG SIMとProcessingでこんなものを作りました.
風呂桶を投げるゲーム
風呂桶の中にスマホを入れています.
手裏剣を投げるゲーム
ZIG SIM
ZIG SIMは株式会社1→10(ワントゥーテン)さんが開発しているプロトタイピング用のスマホアプリです.
「Google Playストア」や「Apple Store」で無料ダウンロードできます.
スマホに搭載しているセンサ(加速度センサ・ジャイロセンサ・GPSなど)のデータを取得して,UDP通信またはTCP通信でPCや他のスマホにデータを送ることができます.
そのため,ProcessingやUnityなどで制作したゲームのコントローラに使えます.
公式資料
アプリの解説をしています.
ここからでもアプリのダウンロードができます.
具体的にどんなデータを取得できるのか,それがどういった形式で送信されるのかを記載しています.
この記事ではさわりしか紹介しないので詳しくはこちらのドキュメントを読んでください.
(もしそれでも分からなかったらTwitterで僕にDMください)
実用例
取得可能なデータ一覧
AndroidとiPhoneによって搭載しているセンサが違います.
共通部分とiPhone限定, Android限定の部分を分けて紹介します.
共通部分
センサ名 | 取得名 |
---|---|
加速度 | accel |
重力加速度 | gravity |
ジャイロ | gyro |
スマホの向き | quaternion |
方位磁石 | compass |
気圧 | pressure |
緯度・経度 | gps |
タッチ座標 | 2d touch |
タッチ圧力 | 3d touch |
近接センサ | proximity monitor |
iPhone
センサ名 | アプリ登録名 |
---|---|
タッチ半径 | touch radius |
位置測定 | beacon |
入力音量 | miclevel |
イヤフォン | remotecontrol |
Android
センサ名 | アプリ登録名 |
---|---|
明るさ | light |
Processingとの通信方法
今回はジャイロセンサとタッチセンシングのやり方を紹介します.
大前提としてスマホとPCを同じWi-Fiに接続してください!!!
なんか通信できないと思ったら各々が繋いだWi-Fiが別だったとかあるあるなので,強調しておきます.
ZIG SIMの設定方法
1. 取得したいセンサにチェックを入れる
今回は「GYRO」と「2D TOUCH」にチェックを入れてください.
2. IP ADDRESS(IPアドレス)を入力する
PCのIPアドレスを入力してください.
調べ方はこちらにまとまっています.
WindowsのIPアドレスの調べ方
MacのIPアドレスの調べ方
3. PORT NUMBER(ポート番号)を入力する
今回は8888
と入力してください.
4. STARTを押す
下段の真ん中にある 「START」を押したら送信開始します.
これでZIG SIM側の準備は大丈夫です!
あとはProcessingでコードを書いて,実行するだけです.
JSONデータの中身
ZIG SIMが送信したJSONデータをProcessingで受信します.
JSONについて分からない方はこちらの記事を参考にしてください.
[Processing] JSONの読み込み書き込み
iPhone
の場合
ZIG SIMが送信するセンサの種類とデータ構造についてからコピペしました.
取得できるセンサを全部チェックいれたときのJSONデータです.
{
"device":{ // 絶対に飛ぶ基本情報
"name" : "iPhone 6s Plus",
"uuid":"0123456789abcdef",
"os":"ios",
"osversion":"10.0.2",
"displaywidth":1920,
"displayheight":1080
},
"timestamp" : "2016/04/06 15:36", // 絶対に飛ぶ基本情報
"sensordata":{
"accel" : { // "ACCEL"選択時に出力される
"x" : 1.00,
"y" : 1.00,
"z" : 1.00
},
"gravity" : { // "GRAVITY"選択時に出力される
"x" : 1.00,
"y" : 1.00,
"z" : 1.00
},
"gyro" : { // "GYRO"選択時に出力される
"x" : 1.00,
"y" : 1.00,
"z" : 1.00
},
"quaternion": { // "QUATERNION"選択時に出力される
"x" : 1.00,
"y" : 1.00,
"z" : 1.00,
"w" : 1.00
},
"compass": { // "COMPASS"選択時に出力される
"faceup": false,
"compass": 180.0
},
"pressure": { // "PRESSURE"選択時に出力される
"pressure" : 1.000,
"altitude" : 1.000
},
"gps": { // "GPS"選択時に出力される
"latitude" : 180.0,
"longitude" : 180.0
},
"miclevel":{
"average":-33.25574493408203,
"max":-26.98263359069824
},
"proximitymonitor":{
"proximitymonitor":false
},
"remotecontrol":{
"volumeup":false,
"playpause":false,
"volumedown":false
},
"touch" : [ // "2D Touch"、"TOUCH RADIUS"、"3D TOUCH"のどれかが選択されていると出力される
{
"x" : 0.5, // "2D Touch"選択時に出力される
"y" : 0.3, // "2D Touch"選択時に出力される
"radius" : 1.0, // "Touch RADIUS"選択時に出力される
"force" : 1.0 // "3D Touch"選択時に出力される
},
{ // 複数のタッチポイントがあれば出力される。iOSの場合最大5点
"x" : 0.1,
"y" : 0.1,
"radius" : 2.0,
"force" : 0.5
},
]
"beacon" : [ // "BEACON"選択時に出力される
{
"uuid" : XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,
"rssi" : -100,
"major" : 100,
"minor" : 1,
},
{ // 複数のBeaconが検出されてれば出力される。
"uuid" : XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,
"rssi" : -50,
"major" : 101,
"minor" : 1,
}
]
}
}
Android
の場合はこちら
自分のスマホから取得しました.
{
"device": {
"displaywidth": 1440,
"os": "Android",
"name": "Pixel 3 XL",
"osversion": "12",
"uuid": "zawa",
"displayheight": 2621
},
"sensordata": {
"proximitymonitor": {"proximitymonitor": false},
"quaternion": {
"w": 0.9159276485443115,
"x": -0.004516989924013615,
"y": -0.0068184928968548775,
"z": 0.401260107755661
},
"compass": {
"compass": -55.99816256785344,
"faceup": 0
},
"light": {"light": 172.96188354492188},
"gravity": {
"x": -0.008886781521141529,
"y": 0.013750473037362099,
"z": 1.0008865594863892
},
"touch": [//2本指で触ったのでデータが2つ取得しています
{
"x": -0.011111111111111072, //2D TOUCHをONにすると取得できます
"y": -0.3216329645173598, //2D TOUCHをONにすると取得できます
"force": 0.2698412835597992 //3D TOUCHをONにすると取得できます
},
{
"x": 0.4194444444444445,
"y": -0.1888592140404426,
"force": 0.1428571492433548
}
],
"pressure": {
"altitude": 0,
"pressure": 1027.0250244140625
},
"gps": {//個人情報なので値は適当なものに変えています
"latitude": 11.4514051,
"longitude": 33.4627737
},
"accel": {
"x": 0.0019250899786129594,
"y": -0.006080803461372852,
"z": -0.005204582121223211
},
"gyro": {
"x": -0.001997369108721614,
"y": 6.657897029072046E-4,
"z": -0.003595264395698905
}
},
"timestamp": "2021/11/29 03:10:57.564"
}
Processingのコード
UDPライブラリのインストール
以下の手順でUDPライブラリをインストールしてください.
Processingの上のバーにある「スケッチ」から「ライブラリをインポート」,「ライブラリを追加」の順に選びます
「Libraries」で「UDP」をインストールしてください(検索バーを使うとすぐ見つかります)
GYROを取得する
こちらのコードをコピペしてください.
import hypermedia.net.*;
UDP udp;
void setup() {
udp = new UDP( this, 8888 );//ZIG SIMの設定と同じにする
udp.listen( true );
}
void draw() {
}
void receive( byte[] data, String ip, int port ) {
if (data == null)return;
String message = new String(data);
JSONObject json = parseJSONObject(message);
JSONObject gyroData = json.getJSONObject("sensordata").getJSONObject("gyro");
float x = gyroData.getFloat("x");
float y = gyroData.getFloat("y");
float z = gyroData.getFloat("z");
println("x: " + x);
println("y: " + y);
println("z: " + z);
println();
}
出力結果
基本的にこの書き方で他のデータも取得できます.
適宜データに合わせて
JSONObject gyroData = json.getJSONObject("sensordata").getJSONObject("gyro");
のgyro
の部分を取得したいデータの名前に変えて
float x = gyroData.getFloat("x");
の部分をx
をの部分を変えたり,型によってはgetFloat()
をgetInt()
やgetBoolean()
に変えてください.
TOUCHを取得する
TOUCH
とBEACON
だけはこんな感じで値を取得します.
import hypermedia.net.*;
UDP udp;
void setup() {
udp = new UDP( this, 8888 );//ZIG SIMの設定と同じにする
udp.listen( true );
}
void draw() {
}
void receive( byte[] data, String ip, int port ) {
if (data == null)return;
String message = new String(data);
JSONObject json = parseJSONObject(message);
JSONArray touchData = json.getJSONObject("sensordata").getJSONArray("touch");
for (int i = 0; i < touchData.size(); i++) {
JSONObject touch = touchData.getJSONObject(i);
float x = touch.getFloat("x");
float y = touch.getFloat("y");
println(i);
println("x: " + x);
println("y: " + y);
println();
}
}
出力結果
ちなみにtouch
においてx
の範囲は(左端) -1 ≦ x ≦ 1 (右端)
で,y
の範囲は(上端) -1 ≦ y ≦ 1
になります.
そのためProcessingの実行画面とサイズを合わせるにはこういう工夫が必要です.
import hypermedia.net.*;
UDP udp;
float ballX, ballY;
void setup() {
size(600, 400);
udp = new UDP( this, 8888 );//ZIG SIMの設定と同じにする
udp.listen( true );
ballX = 0;
ballY = 0;
}
void draw() {
background(0);
fill(255);
ellipse(ballX, ballY, 50, 50);
}
void receive( byte[] data, String ip, int port ) {
if (data == null)return;
String message = new String(data);
JSONObject json = parseJSONObject(message);
JSONArray touchData = json.getJSONObject("sensordata").getJSONArray("touch");
if (touchData.size() > 0) {//一本目の指しか使わないためfor文からif文に変更
JSONObject touch = touchData.getJSONObject(0);
float x = touch.getFloat("x");
float y = touch.getFloat("y");
ballX = (x + 1) * width/2;//工夫部分
ballY = (y + 1) * height/2;//工夫部分
}
}
出力結果
おわりに
この記事だけでZIG SIMとProcessingが連携できるように書いたらめちゃくちゃ長くなってしまいました……
でも,これができれば電子工作しないで自作コントローラを作ることができます!
ぜひZIG SIMとProcessingを組み合わせてコンテンツを作って見てください!
著者プロフィール
こんなの作ってる大学院生です.
Discussion