カジュアルゲーマーを目指して

f:id:saihoooooooo:20191107203609j:plain

Splathon Advent Calendar 2019 の3日目の記事になります。

去年はゼルダBotWのRTAに関する記事を書きましたが今回は普通にスプラトゥーンのTIPSな記事を書きたいと思います。
ちなみに前回当時に約31分だったRTA世界記録は27分53.500秒!!と30分を大きく上回る更新となっているので興味のある方は是非御覧ください。

カジュアルについて

さて、本題ですがタイトルにあるカジュアルゲーマーは読んで字の如く「カジュアルなゲーム」をプレイする人の意味で使っています。
では「カジュアルなゲーム」とは一体何なのか。
これはスプラトゥーン有名プレイヤーのゆっきー氏がとある配信でバブルランチャーの即割でキルされて試合に敗けた際に「カジュアルなゲームになったなぁ」と(自身の持ちブキであるロングブラスターが通用しづらいことも含め)その環境を揶揄したのが発端となり、スプラ界隈でバズった言葉です。

ここからバブル即割そのものを「カジュアル」と呼ぶことも多くなり、ボディビルダーの大会のごとく「ナイスカジュアル!」と味方からの掛け声を貰うことが増えました。
厳密にはおちばシューターによるトーピード即割なのでしょうが、今回は私がここ最近気に入っているボトルガイザーフォイルによるスプラッシュボムでの即割を解説したいと思います。

続きを読む

TypeScriptでアプリのバージョンを取ってくる

例えばAngularでアプリを作っていて、package.json

{
  "name": "super-sharp-spa",
  "version": "0.0.1",
  ...
}

などと書いている場合。

resolveJsonModuleを使えば型定義もなしにjsonの内容をそのままオブジェクトとして取得できる。

www.typescriptlang.org

具体的には下記のように使う。

{
  ...
  "compilerOptions": {
    ...
    "resolveJsonModule": true,
    "esModuleInterop": true
  }
}
import packagejson from '/path/to/package.json';

console.log(packagejson.version); // 0.0.1

便利。

Ionic v3自作プラグインの基礎

Ionic Advent Calendar 2018 の17日目の記事になります。

Ionic界隈ではv4だのCapacitorだので盛り上がっていますが、最近書く機会があったので備忘録程度にv3にて自作プラグイン(Cordova)を追加する方法を書きたいと思います。

プロジェクトの作成

はじめにプロジェクトを作成します。

$ ionic start myApp tabs
$ cd myApp

Cordovaプラグインの作成

次に plugman を使ってCordovaプラグインの雛形を作ります。
入っていない場合はインストールしてください。

$ npm install -g plugman

自作プラグインの作業場所として適当に plugins_src ディレクトリを作ります。
ディレクトリに入り plugman create コマンドを使ってプラグインを作成します。

$ mkdir plugins_src
$ plugman create --name Hoge --plugin_id cordova-plugin-hoge --plugin_version 0.0.0 --path plugins_src

その後 plugman platform add コマンドにてプラットフォームを追加します。
今回はAndroidプラグインを作りますが、iOSの場合は適宜書き換えてください。

$ cd plugins_src/Hoge
$ plugman platform add --platform_name android

結果、下記のような構成が出来ます。

  • plugin.xml プラグインの設定
  • src/android/Hoge.java 実際のAndroidのコードを記述する
  • www/Hoge.js Webviewとのインターフェース
plugins_src/Hoge/
├── plugin.xml
├── src
│   └── android
│       └── Hoge.java
└── www
    └── Hoge.js

中身はこんな感じです。coolMethod、なんてクールな名前なんだ。
やってることは渡ってきた文字列をそのまま返しているだけですね。

<?xml version='1.0' encoding='utf-8'?>
<plugin id="cordova-plugin-hoge" version="0.0.0" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
    <name>Hoge</name>
    <js-module name="Hoge" src="www/Hoge.js">
        <clobbers target="cordova.plugins.Hoge" />
    </js-module>
    <platform name="android">
        <config-file parent="/*" target="res/xml/config.xml">
            <feature name="Hoge">
                <param name="android-package" value="cordova-plugin-hoge.Hoge" />
            </feature>
        </config-file>
        <config-file parent="/*" target="AndroidManifest.xml">
        </config-file>
        <source-file src="src/android/Hoge.java" target-dir="src/cordova-plugin-hoge/Hoge" />
    </platform>
</plugin>
var exec = require('cordova/exec');

exports.coolMethod = function (arg0, success, error) {
    exec(success, error, 'Hoge', 'coolMethod', [arg0]);
};
package cordova-plugin-hoge;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * This class echoes a string called from JavaScript.
 */
public class Hoge extends CordovaPlugin {

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (action.equals("coolMethod")) {
            String message = args.getString(0);
            this.coolMethod(message, callbackContext);
            return true;
        }
        return false;
    }

    private void coolMethod(String message, CallbackContext callbackContext) {
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }
}

今回はこれをちょっと編集してメソッドの実行時に一瞬バイブするよう書き換えたいと思います。
ついでにパッケージ名を変更。

     <platform name="android">
         <config-file parent="/*" target="res/xml/config.xml">
             <feature name="Hoge">
-                <param name="android-package" value="cordova-plugin-hoge.Hoge" />
+                <param name="android-package" value="com.example.hoge.Hoge" />
             </feature>
         </config-file>
         <config-file parent="/*" target="AndroidManifest.xml">
+            <uses-permission android:name="android.permission.VIBRATE" />
         </config-file>
         <source-file src="src/android/Hoge.java" target-dir="src/cordova-plugin-hoge/Hoge" />
     </platform>
-package cordova-plugin-hoge;
+package com.example.hoge;

 import org.apache.cordova.CordovaPlugin;
 import org.apache.cordova.CallbackContext;
@@ -7,6 +7,9 @@ import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;

+import android.content.Context;
+import android.os.Vibrator;
+
 /**
  * This class echoes a string called from JavaScript.
  */
@@ -24,6 +27,7 @@ public class Hoge extends CordovaPlugin {

     private void coolMethod(String message, CallbackContext callbackContext) {
         if (message != null && message.length() > 0) {
+            ((Vibrator) cordova.getActivity().getSystemService(Context.VIBRATOR_SERVICE)).vibrate(100);
             callbackContext.success(message);
         } else {
             callbackContext.error("Expected one non-empty string argument.");

最後にプラグインのインストール時に必要となるpackage.jsonを下記のコマンドで作成します。

$ plugman createpackagejson .

CordovaプラグインのIonic Native化

これでCordovaプラグインは完成しましたがIonicで使うためにIonic Native化(Typescript化)します。
任意の場所に ionic-team/ionic-native を置きます。
今回は例として本家を直接サブモジュール化していますが実際使うならフォークしたものを使用してください。
gulp plugin:create -n [プラグイン名]で雛形を作成します。

$ cd ../..
$ git submodule add https://github.com/ionic-team/ionic-native plugins_src/ionic-native
$ cd plugins_src/ionic-native/
$ npm install
$ gulp plugin:create -n Hoge

src/@ionic-native/plugins/hoge/index.tsが出来上がるので下記の様に編集します。
import文はtslintさんが怒ってくるので。

  *
  */
 import { Injectable } from '@angular/core';
-import { Plugin, Cordova, CordovaProperty, CordovaInstance, InstanceProperty, IonicNativePlugin } from '@ionic-native/core';
+import { Cordova, CordovaInstance, CordovaProperty, InstanceProperty, IonicNativePlugin, Plugin } from '@ionic-native/core';
 import { Observable } from 'rxjs/Observable';

 /**
@@ -36,24 +36,23 @@ import { Observable } from 'rxjs/Observable';
  */
 @Plugin({
   pluginName: 'Hoge',
-  plugin: '', // npm package name, example: cordova-plugin-camera
-  pluginRef: '', // the variable reference to call the plugin, example: navigator.geolocation
+  plugin: 'cordova-plugin-hoge', // npm package name, example: cordova-plugin-camera
+  pluginRef: 'cordova.plugins.Hoge', // the variable reference to call the plugin, example: navigator.geolocation
   repo: '', // the github repository URL for the plugin
   install: '', // OPTIONAL install command, in case the plugin requires variables
   installVariables: [], // OPTIONAL the plugin requires variables
-  platforms: [] // Array of platforms supported, example: ['Android', 'iOS']
+  platforms: ['Android'] // Array of platforms supported, example: ['Android', 'iOS']
 })
 @Injectable()
 export class Hoge extends IonicNativePlugin {

   /**
    * This function does something
-   * @param arg1 {string} Some param to configure something
-   * @param arg2 {number} Another param to configure something
+   * @param message {string} Some param to configure something
    * @return {Promise<any>} Returns a promise that resolves when something happens
    */
   @Cordova()
-  functionName(arg1: string, arg2: number): Promise<any> {
+  coolMethod(message: string): Promise<any> {
     return; // We add return; here to avoid any IDE / Compiler errors
   }

ビルドします。
成果物は dist/@ionic-native/hoge に置かれます。
これで準備は整ったのでプロジェクト直下に戻ります。

$ npm run build hoge
$ cd ../..

Ionicで実装

最後に実際に使うIonic側のコードを記述します。
src/app/app.module.ts に登録した後、 src/pages/home/home.ts にメソッドを追加してボタンで呼ぶようにします。

 import { StatusBar } from '@ionic-native/status-bar';
 import { SplashScreen } from '@ionic-native/splash-screen';
+import { Hoge } from '@ionic-native/hoge';

 @NgModule({
   declarations: [
@@ -34,6 +35,7 @@ import { SplashScreen } from '@ionic-native/splash-screen';
   providers: [
     StatusBar,
     SplashScreen,
+    Hoge,
     {provide: ErrorHandler, useClass: IonicErrorHandler}
   ]
 })
 import { Component } from '@angular/core';
 import { NavController } from 'ionic-angular';
+import { Hoge } from '@ionic-native/hoge';

 @Component({
   selector: 'page-home',
@@ -7,8 +8,14 @@ import { NavController } from 'ionic-angular';
 })
 export class HomePage {

-  constructor(public navCtrl: NavController) {
+  constructor(public navCtrl: NavController, public hoge: Hoge) {

   }

+  coolMethod() {
+    this.hoge.coolMethod('aaaa').then(message => {
+      alert(message);
+    });
+  }
+
     Take a look at the <code>src/pages/</code> directory to add or change tabs,
     update any existing page or create new pages.
   </p>
+  <button ion-button (click)="coolMethod()">coolMethod</button>
 </ion-content>

プラグインをインスールして実機で確認。

$ ionic cordova plugin add plugins_src/Hoge
$ npm install plugins_src/ionic-native/dist/@ionic-native/hoge
$ ionic cordova run android --device

COOLMETHODボタンを押すたびに端末がブルブルと震えるようになりました。
やったね。

f:id:saihoooooooo:20181214164955j:plain:w300

まとめ

初歩の初歩ですが割と簡単にできたと思います。
Capacitorだともっと楽にネイティブの機能を呼び出せるっぽいので期待ですね。

ゼルダの伝説BotWのRTAが俺を惹きつけてやまない

※この記事はスプラトゥーンの話題を含みません。
※この記事はゼルダの伝説BotWのネタバレを含みます。

Splathon Advent Calendar 2018 の11日目の記事になります。

まえがき

ゼルダの伝説BotW面白いですね。
「記憶をなくしてもっかいやりたい」なんて声がちらほら聞こえてくる正真正銘のザ・神ゲーです。
僕も発売当時はSplathonの#zeldaチャンネル、#zelda_netabareチャンネルに入り浸り、そしてハイラルに入り浸り、やがて現実との区別がつかなくなり、仕事中にもかかわらず「早く現実(ハイラル)に戻りたい...早く...」と呟きながらポロポロと涙をこぼしていました。

RTAとAny%について

そんなゼルダの伝説BotWの面白さのひとつがとにかく「自由」であるということ。
自由すぎてチュートリアル終了後はストーリーを全無視していきなりラスボスに挑戦することも可能だったりします。
ツール等を使わずに人力でのゲームクリアまでのタイムを競うことをRTA(Real Time Attack)と呼びますが、ゼルダの伝説BotWはとってもRTA向きなゲームだと言えるでしょう。

また一口にRTAと言っても複数のレギュレーションが存在しており、その中でも今回は最も一般的であろうAny%というレギュレーションに注目したいと思います。
これは要するにダンジョンやイベントの進行度、そのルート等を一切考慮しない純粋なクリア時間を競うもので、ゼルダの伝説BotWではオープニングムービーが終わってリンクを操作できるようになった瞬間から魔獣ガノンに最後の光の矢が当たるまでの時間を計測します。

Any%の世界記録

現在の記録は果たしてどれほどなのか、タイムアタックの記録集積サイトのspeedrun.comで確認してみましょう。

続きを読む

ErgoDox買ったったった(そしてハウツーConfigurator)

巷で話題のセパレートキーボード、ErgoDox買っちゃった俺マジ異端児。
こんばんわ、saihooooooooです。
フリースタイルラップのTV番組を見ながら記事を書いてしまいました。

という訳でErgoDoxですが、ご存知でしょうか。
ErgoDox is 何?という方は下記サイトを御覧ください。
自分もこの記事に触発されて買ったクチです。

nippondanji.blogspot.jp

もともと自分も無駄にガタイが良いためか肩こりがひどく、エルゴノミクスキーボードというものを知ってからは同じくセパレート型キーボードであるKinesis Freestyleを愛用していました。
Kinesis Freestyleはとても良い製品で特に不満も無かったのですが、ErgoDoxの「オープンソースキーボード」というイケてる響きにミーハーな僕は飛びついてしまいました。

続きを読む