2014年12月25日木曜日

納品のない受託開発でお馴染みのソニックガーデンの「ギルド」にチャレンジしてみた

9月ごろネットを見ていら「納品のない受託開発」という本の広告が目に着いた。
(たぶん、Amazonで何かの本を買った関連本として広告が出てきたのだと思う)



タイトルになんとなく引かれて広告をクリックし、Amazonでどんな本かを調べる。
面白そう、 読んでみようかなと思った。

その前に、作者である、「」さんとは何者だ?
と思い、検索してみると
ソニックガーデンという会社を経営しているようだ。

その会社のホームページを見ると、「ギルド」という制度があり
エンジニアを募集しているようである。

単なる求人ではなく、フランチャイズのような制度である。

私はフリーランスとしてソフトウエアエンジニアをやっているが、
サラリーマンと違い、収入が安定しない。
どっかの企業に常駐すれば収入は安定するが、それだと、サラリーマンと変わらない。

在宅で時間にとらわれずにノマド的に仕事がしたいというのが、私の希望である。

このギルドという制度は、

・副業としても参加でき、フリーランスのままでもギルドに参加が出来きる
・東京近郊だけでなく、日本全国・世界各地からギルドに参加出来きる
という。


これ、いいじゃん!
フリーランスの私にピッタリ。
まさに私のためにある制度だ、と勘違いしギルド登録に申し込んだ。

といってもいきなり申し込んだわけではない。

ギルドに参加するために必要なスキルとして、
・Ruby on Railsでのウェブアプリケーションの開発経験

というのがあった。

Railsなんて触ったことないし...

とりあえず勉強しよっか。
そして、実力がついたら。。。いつか申し込もう。

と思った自分に、もう一人の自分が問いかける。
「いつか」っていつですか? 

うーん、じゃあ、一ヶ月後。
ということで、約一ヶ月後の「10/20」に申し込むという期限を決めた。


そして1ヶ月間、
ネット上のチュートリアル
Ruby on Rails 4 アプリケーションプログラミング
RailsによるアジャイルWebアプリケーション開発(第4版)
によってRailsを学び、申し込むことにした。

次回に、つづく。

2014年11月16日日曜日

「好きなこと」を仕事にする

「好きなこと」を仕事にするには、
ずっと続けられる「好きな作業」を見つけて取り組むことが必要なのです。
http://laugh-raku.com/archives/11295 より

長時間やっても苦にならない作業はどれですか?

作業
・文章を書く
・人と話す
・体を動かす
・同じことを繰り返す
・机にずっと座っている
・計算をする

2014年8月16日土曜日

モグラ叩きゲームで学ぶアンドロイドプログラミング (8/8)

前回は、音楽を付けるところまでやりました。
今回は、あまりにも簡単すぎるのでゲームの難易度を少し上げようと思います。

全体のソースコードは以下にあります。
https://gist.github.com/mrp1q7z/d42c75408e7a62683428

もぐらは出てきたらずっと同じ位置にいるのでゲームとしては簡単すぎて面白くありません。そこで、出てきて一定時間たったら引っ込み、別の場所に出るというように、神出鬼没にしてみたいと思います。

もぐらを引っ込めるためのタイマーを宣言します。(45行目)
private Timer mMoleTimer = null;

もぐらを表示する際、一定時間経過したら引っ込める処理を記述します。(181行目〜)
if (mMoleTimer != null) {
    mMoleTimer.cancel();
}
long delay = (long) (Math.random() * (1000 - 100) + 100);
mMoleTimer = new Timer(true);
mMoleTimer.schedule(new TimerTask() {
    @Override
    public void run() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                printMole();
            }
        });
    }
}, delay);

100〜1000までの乱数を発生させてこれを表示時間(ミリ秒)としています。

ゲームオーバー時にタイマーの終了処理を行います。(134行目〜)
mMoleTimer.cancel();
mMoleTimer = null;

実行してみます。
もぐらがヒョコヒョコとあちこちに出てくるようになったと思います。
難易度も上がってなかなかスコアが伸びません。


ただここで問題が...
もぐらを叩こうとがんばっていると、「Game Over」が出てきて
出てきた瞬間にタップしてしまうので、すぐにリプレイされてしまいます。

そこで、「Game Over」をしばらく表示しておくようにします。
画面を修正、「画面タップでリプレイ」という文字にIDを付けます。
<TextView
    android:id="@+id/replay_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/game_over_text"
    android:layout_centerHorizontal="true"
    android:text="画面タップでリプレイ"
    android:textSize="20sp"
    android:textColor="#888888"/>

この文字を保持する変数を宣言します。(46行目)
private TextView mReplayText;

変数に値をセットします。(64行目)
mReplayText = (TextView) findViewById(R.id.replay_text);

ゲームスタート時に非表示にします。(107行目)
mReplayText.setVisibility(View.INVISIBLE);

ゲームオーバー時に2秒後に表示するようにします。(137行目〜)
Timer timer = new Timer(true);
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mReplayText.setVisibility(View.VISIBLE);
            }
        });
    }
}, 2000);

Game Over をタップしても「画面タップでリプレイ」が表示されていない場合は、何もしないようにします。(217行目〜)
if (mReplayText.getVisibility() != View.VISIBLE) {
    return;
}

実行してみます。
「画面タップでリプレイ」が表示されてないときはリプレイしなくなりました。

結構ゲームらしくなりました。
まだまだ改善の余地はあると思いますが、「モグラ叩きゲームで学ぶアンドロイドプログラミング」はこれにて終了とします。

長らくのお付き合いありがとうございました。

アプリは Google Play にて公開しています。

ソースコードは GitHub で公開しています。
https://github.com/mrp1q7z/WhacMole
※ライセンスはGPLv3となっています。
※以下のファイルは「小森平」さん(http://taira-komori.jpn.org/)の著作です。
res/raw/middle_punch1.mp3
res/raw/swing1.mp3

2014年8月15日金曜日

モグラ叩きゲームで学ぶアンドロイドプログラミング (7/8)

前回は、Game Overを出すところまでやりました。
今回は、音楽でも付けてよりゲームらしくします。

全体のソースコードは以下にあります。
https://gist.github.com/mrp1q7z/49d45fea537c07d6a202

その前に最初のスコアが100になっているので0にします。
<TextView
android:id="@+id/scoreText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0"
android:textSize="30sp" />

activity_main.xmlの「text="100"」を「text="0"」に変更します。

適当な効果音を探してきます。
今回は、以下にしました。ありがとうございました。
・「middle_punch1/中打」「swing1/素振り1」 by 小森平さん
http://taira-komori.jpn.org/attack01.html

※音楽や画像の素材を利用する場合は利用規約をよく読んで違反なきよう使いましょう。

ダウンロードした効果音を「res/raw」にコピーします。
「raw」フォルダがない場合は新たに作成します。


ソースを変更していきます。
効果音を鳴らすために必要な変数を宣言します。(29行目〜)
private SoundPool mSound;
private int[] mSoundId;


効果音をロードします。(37行目〜)
mSoundId = new int[2];
mSound = new SoundPool(mSoundId.length, AudioManager.STREAM_MUSIC, 0);
mSoundId[0] = mSound.load(getApplicationContext(), R.raw.middle_punch1, 0);
mSoundId[1] = mSound.load(getApplicationContext(), R.raw.swing1, 0);


ボタンをクリックしたときに効果音を再生するようにします。(158、161行目)
private View.OnClickListener mButtonClicked = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (view != mMoleButton) {
            mSound.play(mSoundId[1], 1.0F, 1.0F, 0, 0, 1.0F);
            return;
        }
        mSound.play(mSoundId[0], 1.0F, 1.0F, 0, 0, 1.0F);

    ....
}
もぐらを叩いた時と穴を叩いた時で再生する音を変えています。

終了時に効果音の開放を行います。(138行目〜)
@Override
public void onDestroy() {
    super.onDestroy();
    mSound.release();
}

実行してみます。
音が出るようになったと思います。

今日はここまで。次回に続く。

2014年8月14日木曜日

モグラ叩きゲームで学ぶアンドロイドプログラミング (6/8)

前回は、もくらを叩くとスコアが+1されるところまでやりました。
今回は、もぐらを叩いたら次の場所にもぐらが出現するようにします。

全体のソースコードは以下にあります。
https://gist.github.com/mrp1q7z/f1ef3c7940cb58366de2

スコアを+1するタイミングでもぐらを表示してやります。(148行目)
printMole();
mButtonClickedに上記処理を追加します。

実行してみます。


もぐらを叩くと別の場所にもぐらが現れるようになりました。
が、前の位置にもぐらが残ったままになります。

もぐらを表示するときに、前のもぐらを消すようにします。(130行目〜)
if (mMoleButton != null) {
    mMoleButton.setBackgroundResource(R.drawable.bg_button);
}


実行してみます。


前のもぐらが消えるようになりました。

だんだんゲームらしくなってきました。
が、タイムが0になったのにゲームが続けられます。
これを直します。

タイムアウトしたら半透明の幕を出して操作できないようにします。
レイアウトファイルを修正します。


赤い部分が変更で、黄色い部分が追加したところです。
黄色い部分は「android:visibility="invisible"」にして、表示しないようにしておきます。

プログラムソースの方も変更します。
ゲームオーバーの幕を保持する変数を宣言します。(26行目)
private RelativeLayout mGameOver;

変数に値をセットします。(37行目)
mGameOver = (RelativeLayout) findViewById(R.id.game_over_container);

ゲームオーバーしたら幕を表示するようにします。(108行目)
mGameOver.setVisibility(View.VISIBLE);

幕をクリックしたときの処理を記述します。(152行目〜)
private View.OnClickListener mGameOverClicked = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        mGameOver.setVisibility(View.INVISIBLE);
        mScore = 0;
        String strScore = String.valueOf(mScore);
        mScoreText.setText(strScore);
        mGameTime = 60;
        gameStart();
    }
};

クリックと処理を紐付けます。(38行目)
mGameOver.setOnClickListener(mGameOverClicked);

実行してみます。


今日はここまで。次回に続く。




2014年8月12日火曜日

モグラ叩きゲームで学ぶアンドロイドプログラミング (5/8)

更新が遅くなってしまい、すいません。
さて、前回に引き続き、今回は、もぐらを叩いたときの処理を実装します。

全体のソースコードは以下にあります。
https://gist.github.com/mrp1q7z/c5a1f8eaedd419c018a4


画面 (activity_main.xml) を一部修正します。
スコアを表示するテキストにID(名前)を付けます。
IDはプログラムから参照するものだけ付にけます。
参照しないものについては付けなくてもOKです。

「scoreText」という名前にしました。


次に、プログラムからスコアを操作するための変数を定義します。(19行目)
private TextView mScoreText;
定義した変数に値をセットします。(33行目)
mScoreText = (TextView) findViewById(R.id.scoreText);

スコアを管理する変数も定義します。(20行目)
private int mScore;
スコアを初期化します。(32行目)
mScore = 0;

ボタンがクリックされたときの処理を記述します。(131行目〜)
private View.OnClickListener mButtonClicked = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        mScore++;
        String strScore = String.valueOf(mScore);
        mScoreText.setText(strScore);
    }
};

とりあず、スコアを1ずつ増やしていくようにします。

ボタンと上記処理を紐付けます。(61行目〜)
for (int row = 0; row < mButton.length; row++) {
    for (int col = 0; col < mButton[1].length; col++) {
        mButton[row][col].setOnClickListener(mButtonClicked);
    }

}
ここまでできたら実行してみましょう。


ボタンをクリックするとスコアが1ずつ増えていくと思います。
ただ、どのボタンでもスコアが増えていくので、もぐらがいるかどうかの
判定をするようにします。

もぐらがどのボタンに表示されているかを管理するための変数を定義します。(18行目)
private Button mMoleButton;
上記変数を初期化します。 (31行目)
mMoleButton = null;
もぐらを表示するときに上記変数に値をセットします。(128行目)
mMoleButton = mButton[row][col];

ボタンがクリックされたときの処理で判定を行います。(134行目)
if (view != mMoleButton) {
    return;
}

もぐらでない場合は何もせずに戻るようにします。

ここまでできたら実行してみましょう。


もぐらをクリックしたときはスコアが増えて、他の場所をクリックしたときは何も起きないようになったと思います。

今日はここまで。次回に続く。




2014年7月28日月曜日

Ubuntu14.04にCordovaの開発環境を構築してFirefoxOSとAndroidアプリを作ってみる

画面が切り替わるようにする 編


今回は画面が切り替わるようにする。

1. ライブラリの導入

前回、画面を追加したが、画面が重なったままだった。これをまずはなんとかする。
いよいよJavaScriptを書く訳だが、ここで便利なライブラリを導入する。

Backbone.js
ごちゃごちゃになりがちなJavaScriptをすっきりした状態にしてくれる。
ModelとViewにレイヤー分けしてJavaScriptが読みやすくなる。

http://backbonejs.org/ よりbackbone-min.jsをダウンロード。

Backbone.jsは以下のライブラリに依存しているのでこれもダウンロード。
Underscore.js ( >= 1.4.3) またはLo-Dash
json2.js
jQuery ( >= 1.7.0)またはZepto

全部、www/jsフォルダにコピー。
www/index.htmlに以下を追加。
<script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="js/json2.js"></script>
<script type="text/javascript" src="js/underscore-min.js"></script> 
<script type="text/javascript" src="js/backbone-min.js"></script>
ソースのコメント:@@@1

2. 重なった画面をなおす

JavaScriptで画面を切り替える。
Opening画面だけを表示して他は非表示にする。

www/js/index.jsに以下を追加。
var ViewOpening = Backbone.View.extend({
    el : "#opening",
});

var ViewSettings = Backbone.View.extend({
    el : "#settings",
});

var ViewMain = Backbone.View.extend({
    el : "#main",
});

var viewOpening = new ViewOpening;
var viewSettings = new ViewSettings;
var viewMain = new ViewMain;
var view = {
    showOpening: function() {
        viewOpening.$el.show();
        viewSettings.$el.hide();
        viewMain.$el.hide();
    },
    showSettings: function() {
        viewOpening.$el.hide();
        viewSettings.$el.show();
        viewMain.$el.hide();
    },
    showMain: function() {
        viewOpening.$el.hide();
        viewSettings.$el.hide();
        viewMain.$el.show();
    },
};
 
view.showOpening(); 
ソースのコメント:@@@2

3. 設定画面を表示

オープニング画面の右上のギア(設定アイコン)を押すと設定画面に切り替わるようにする。

まず、ギア(設定アイコン)にIDを付ける。
www/index.htmlに以下を追加。
<span id="settings_button" class="icon icon-settings">settings</span>

www/js/index.jsに以下を追加。
var ViewOpening の中に追加

    events : {
        "click #settings_button" : "settingsButtonClicked",
    },
    
    settingsButtonClicked: function() {
        view.showSettings();
    },
ソースのコメント:@@@3

4. 設定から戻る

設定画面が表示されるようになった。
今度は、「done」を押すとオープニング画面に戻るようにする。

「done」ボタンにIDを付ける。
www/index.htmlに以下を追加。
<button id="settings_done">done</button>

www/js/index.jsに以下を追加。
var ViewSettings の中に追加

    events : {
        "click #settings_done" : "settingsDoneClicked",
    },
    
    settingsDoneClicked: function() {
        view.showOpening();
    },
ソースのコメント:@@@4

5. メイン画面を表示

オープニング画面の「Start」ボタンを押すとメイン画面に切り替わるようにする。

「Start」ボタンにIDを付ける。
www/index.htmlに以下を追加。
<button id="start_button">Start</button>

www/js/index.jsに以下を追加。
var ViewSettings の中に追加

    events : {
        "click #settings_done" : "settingsDoneClicked",
        "click #start_button" : "startButtonClicked", //これを追加
    },
    
    startButtonClicked: function() {
        view.showMain();
    },
ソースのコメント:@@@5

今日の全ソースはこちら

これで、Cordovaで「Hello World」はおしまい。

次回は、これをベースにしてちょっとしたアプリを作ってマーケットプレイスにリリースするまでをやりたい。

2014年7月26日土曜日

Ubuntu14.04にCordovaの開発環境を構築してFirefoxOSとAndroidアプリを作ってみる

画面を追加 編


今回はいくつか画面を追加し、画面が切り替わるようにする。

1. 最初の画面を整える

まず、Hello World の最初の画面をオープニング画面として整える。

タイトルを「Apache Cordova」から「Opening」 に変える。
www/index.html
<h1>Apache Cordova</h1>
↓
<h1>Opening</h1>

画面下部に「Start」ボタンを付ける。
www/index.html
<link rel="stylesheet" type="text/css" href="shared/style/buttons.css" />

<br />
<div class="bb-docs skin-organic">
    <button>Start</button>
</div>

<div class="app">〜</div> の部分を <section id="opening" の中に入れる。
www/index.html
</section> <!-- これを移動 -->
    <script type="text/javascript" src="cordova.js"></script>
ソースのコメント: @@@1


2. 画面を追加する

設定画面を追加する。
www/index.html
<section id="settings" role="region" class="current" data-position="current">
    <header>
        <menu type="toolbar">
            <button>done</button>
        </menu>
        <h1>Settings</h1>
    </header>
    <div class="app">
        <h1>Settings</h1>
    </div>
</section>
ソースのコメント: @@@2

メイン画面を追加する。
www/index.html
<section id="main" role="region" class="current" data-position="current">
    <header>
        <h1>Main</h1>
    </header>
    <div class="app">
        <h1>Main</h1>
    </div>
</section>
ソースのコメント: @@@3






画面が重なっている。
これは、JavaScript で必要ない画面を非表示にする処理が必要。

が、今回はここまで。
ソースはこちら

2014年7月21日月曜日

Ubuntu14.04にCordovaの開発環境を構築してFirefoxOSとAndroidアプリを作ってみる

FirefoxOSぽい外観の作成 編


今回は画面を作っていく。

1. 画面上部のオレンジ色のヘッダを作る

Gaiaというツールを導入すれば簡単に作れるらしい。
mozilla-b2g/gaiaをダウンロード。
その中の「shared」フォルダを www フォルダにコピー。
www/index.htmlを修正。
<link rel="stylesheet" type="text/css" href="shared/style/headers.css" />

<section id="opening" role="region" class="current" data-position="current">
  <header>
    <h1>Hello World</h1>
  </header>
</section>
ソースのコメント: @@@1

文字が勝手に大文字になるので、www/css/index.cssを修正。
  text-transform:uppercase; /* これをコメントアウト */
ソースのコメント: @@@2

タイトルを左寄せにしてアイコンをつける。
www/css/index.css
section[role="region"] > header:first-child h1 {
  text-align: left;
}
header h1 {
    background:url(../img/logo.png) 0 50% no-repeat;
    -moz-background-size:contain;
    background-size:contain;
    padding-left: 5rem !important;
}
ソースのコメント: @@@3
※どういう訳かpadding-leftが効かなかったので!importantを付けた。


タイトルの右上にメニューアイコン(設定アイコン)を付ける。
www/index.html
<menu type="toolbar">
    <a href="#"><span class="icon icon-settings">settings</span></a>
</menu>
ソースのコメント: @@@4

www/css/index.css
section[role="region"] > header:first-child .icon.icon-settings {
  background-image: url(../img/settings@2.25x.png);
}
ソースのコメント: @@@4

www/img/に画像をコピー
・settings.png  (30x30)
・settings@1.5x.png  (45x45)
・settings@2.25x.png  (68x68)





タイトルが途中で切れるので、www/css/index.cssを修正。
font-size: 1.3rem !important; /* これを追加 */
ソースのコメント: @@@5




全ソースはここ

今日はここまで。

2014年7月16日水曜日

Ubuntu14.04にCordovaの開発環境を構築してFirefoxOSとAndroidアプリを作ってみる

Hello World + adMob 編


1. サンプルアプリ(Hello World)の作成

適当なフォルダ(例:/home/user/CordovaProject)で、以下を実行。
$ cordova create HelloWorld com.example.hello "Hello World"
create 時に指定するパラメータの意味。
第1パラメータ(HelloWorld):フォルダ名
第2パラメータ(com.example.hello):ドメインの逆順+アプリ名
第3パラメータ("Hello World"):表示されるアプリの名前

上記コマンドを実行すると「HelloWorld」というフォルダが作成され、その中にアプリのひな形が作られる。

アプリのフォルダに移動。
$ cd HelloWorld

ターゲットを追加。
$ cordova platform add firefoxos
$ cordova platform add android

ターゲットの確認。
$ cordova platform ls
Installed platforms: android 3.5.0, firefoxos 3.5.0
Available platforms: amazon-fireos, blackberry10, ubuntu

2. 実行してみる

Androidの実機をUSBで接続して、以下を実行。
※事前に /etc/udev/rules.d/51-android.rules を作成しデバッグできる状態にしておくこと。
例(LGの場合):「SUBSYSTEM=="usb", ATTR{idVendor}=="1004", MODE="0666", GROUP="plugdev"」
$ cordova run android
エミュレータで実行する場合は、以下を実行。
※事前に「android avd」で仮想マシンを作成しておくこと
$ cordova emulate android

動いた!

Firefox OS の場合は実機がないのでFirefox OS Simulatorで動かす。

↑よりSimulatorをインストール。

Firefoxでアプリマネージャ(about:app-manager)を起動。

パッケージアプリを追加し、「HelloWorld/platforms/firefoxos/www」を選択

なんか、manifest.webappにiconsがないとエラーになる。
manifest.webappsに「"icons": {"128": "/img/logo.png"}」を追加。

動いた!

Firefox OS SimulatorはAndroidのように重くなくて良い。実に軽くて早い。
これからは、Firefox OS 向けにアプリを書いてテストしたあと
Androidに持っていたほうが開発がやりやすいかな?

3. アプリに広告を出したいのでadMobを追加

adMobプラグインを追加
$ cordova plugin add https://github.com/MobileChromeApps/google-play-services.git
$ cordova plugin add https://github.com/floatinghotpot/cordova-plugin-admob.git

www/js/index.js をエディタで開き、以下を追加。

※コメントで「+++ add adMob」と書いてあるところを追加した。
※Androidのときだけ表示するようにしてある。(FirefoxOSで動かすとエラーが出たので...)

adMobが表示された!

続きはまた。

Ubuntu14.04にCordovaの開発環境を構築してFirefoxOSとAndroidアプリを作ってみる

開発環境の構築編


1. JDKのインストール

途中、ライセンスに同意するか聞かれるので「はい」を選択する。
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java7-installer
$ java -version
java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) Server VM (build 24.60-b09, mixed mode)

2. Android SDKのインストール

Android SDKだけでもいいのだが、あったほうが便利なので、Android Studioを入れる。
※Android Studio には Android SDKが付属してある。

https://developer.android.com/sdk/installing/studio.html よりダウンロード

(どこでもいいのだが)/usr/localに入れる。
$ cd /usr/local
$ sudo tar -xvzof /tmp/android-studio-bundle-135.1245622-linux.tgz
$ sudo chown -R $USER:$USER /usr/local/android-studio

環境変数のセット
$ echo 'export PATH=$PATH:/usr/local/android-studio/sdk/tools:/usr/local/android-studio/sdk/platform-tools:/usr/local/android-studio/bin' >> .bashrc
$ echo 'export ANDROID_HOME=/usr/local/android-studio/sdk' >> .bashrc

※64ビットのUbuntuの場合は、ia32-libsのインストールが必要。
$ sudo apt-get install ia32-libs

3. Android SDK Managerでツールのインストール

$ android
※パスが通ってない場合はターミナルを再起動
Android SDK Manager が起動するので以下を選択してインストール

  • Android SDK Tools
  • Android SDK Platform-tools
  • Android SDK Build-tools
  • Android 4.4.2 (API 19)
  • Android 2.3.3 (API 10)

4. Cordovaのインストール

$ sudo apt-get install nodejs
$ sudo apt-get install npm
$ sudo npm install -g cordova
$ cordova -v
3.5.0-0.2.6

nodeがないというエラーが出たので
sudo ln -s /usr/bin/nodejs /usr/bin/node
を追加して「sudo npm install -g cordova」からやり直し。今度は動いた。

5. Antのインストール

Androidの開発をするには必要。
$ sudo apt-get install ant
$ ant -version
Apache Ant(TM) version 1.9.3 compiled on December 3 2014

以上で環境構築は終わり。
続きはまた。

2014年7月12日土曜日

Arch Linux (Manjaro/openbox)にCordovaの開発環境を構築してFirefoxOSとAndroidアプリを作ってみる

開発環境の構築編

1. JDKのインストール
sudo pacman -S jdk7-openjdk
java -version
※今回はOpenJDKにしてみた

2. Android SDKのインストール
(どこでもいいのだが)/usr/localに入れる。
$ cd /usr/local
$ sudo tar -xvzof /tmp/android-studio-bundle-135.1245622-linux.tgz
$ sudo chown -R $USER:users /usr/local/android-studio

環境変数のセット
$ echo 'export PATH=$PATH:/usr/local/android-studio/sdk/tools:/usr/local/android-studio/sdk/platform-tools:/usr/local/android-studio/bin' >> .bashrc
$ echo 'export ANDROID_HOME=/usr/local/android-studio/sdk' >> .bashrc

3. Android SDK Managerでツールのインストール
$ android
※パスが通ってない場合はターミナルを再起動
Android SDK Manager が起動するので以下を選択してインストール

    Android SDK Tools
    Android SDK Platform-tools
    Android SDK Build-tools
    Android 4.4.2 (API 19)
    Android 2.3.3 (API 10)


4. Cordovaのインストール

cd
curl https://raw.githubusercontent.com/creationix/nvm/v0.11.2/install.sh | bash
ホーム直下に「.nvm」というフォルダが作成され、そこにインストールされる。

.bashrcに以下を追加
source ~/.nvm/nvm.sh

ターミナルを開きなおして
nvm ls-remote
でインストール可能なバージョン一覧を表示。

必要なバージョンのnodejsをインストール。
nvm install 0.10.29
偶数が安定バージョン、奇数が開発バージョンらしい。

.bashrcに以下を追加
nvm use v0.10.29

ターミナルを開きなおして
$ node -v
v0.10.29
$ npm -v
1.4.14
$ sudo npm install -g cordova
$ cordova -v
3.5.0-0.2.6

5. Antのインストール
Androidの開発をするには必要。
$ sudo pacman -S apache-ant
$ ant -version
Apache Ant(TM) version 1.9.4 compiled on June 14 2014



ごめんなさい。
ここで力つきました。

2014年7月3日木曜日

Android emulator 内のブラウザが起動しない

OS: elementary OS (Ubuntu 12.04 base)
 
次のような Android エミュレータを作り、ブラウザを起動すると...



E/EGL_emulation(2637): Failed to establish connection with the host というエラーが出る。
 
NVIDIA のドライバーを変えたら動いた。
 

2014年4月12日土曜日

モグラ叩きゲームで学ぶアンドロイドプログラミング (4/8)

前回に引き続き、今回は、タイマーの処理を実装します。

全体のソースコードは以下にあります。
https://gist.github.com/mrp1q7z/cdae635e02c16c1cb9e9


画面 (activity_main.xml) を一部修正します。
残り時間を表示するテキストにID(名前)を付けます。
IDはプログラムから参照するものだけ付けます。
参照しないものについては付けなくてもOKです。

「timeText」という名前にしました。



次に、プログラムから残り時間を操作するための変数を定義します。(17行目)
private TextView mTimeText;

定義した変数に値をセットします。(27行目)
mTimeText = (TextView) findViewById(R.id.timeText);

次に、残り時間をカウントダウンするための変数を定義します。(18行目)
private int mGameTime = 60;
あらかじめ「60」とう値をセットしていますが、これは60秒という意味です。
この値を変えると残り時間を変更することができます。

次に、タイマーのような一定時間で処理を繰り返すには「Timer」というクラスを使います。そのための変数を定義します。(19行目)
private Timer mTimer = null;

次に、「gameStart」というメソッドを追加して、ゲームスタート時の処理を記述します。(64〜86行目)

private void gameStart() {
        printMole();

        if (mTimer != null) {
            return;
        }
        mTimer = new Timer(true);
        mTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mGameTime--;
                        if (mGameTime <= 0) {
                            gameOver();
                        }
                        mTimeText.setText(Integer.toString(mGameTime));
                    }
                });
            }
        }, 1000, 1000);

}

65行目:モグラを表示するメソッド「printMole」を呼びます。(前回、onResumeから呼び出していたもの)

67〜69行目:すでにタイマーがスタートしているかを判定し、すでにスタートしている場合は処理を抜けます。

70行目:タイマー変数の初期化

71行目:scheduleAtFixedRate(TimerTask task, long delay, long period)は、delayミリ秒あとの時間を基準としてperiodミリ秒単位でタスクを繰り返す。今回の場合だと、71行目の「new TimerTask() {」〜85行目の「}」までがタスクで、85行目の1つめの1000がdelay、2つめの1000がperiodになります。

タスクの中では、mGameTimeをカウントダウンして(77行目)
0以下になったら gameOver メソッドを呼び出して(78〜80行目)
残り時間を画面に表示(81行目)
しています。

途中の run() を Override していたり、
mHandler.post() だったりは
意味が分からなくてもこんなもんだと思っていただければOKです。

次に、「gameOver」メソッドを追加し、ゲーム終了時の処理を記述します。(88〜91行目)
private void gameOver() {
        mTimer.cancel();
        mTimer = null;
}


タイマーをキャンセルして、変数をヌルで初期化しています。

最後に、onResume の printMole を gameStart に置きかえます。(96行目)
protected void onResume() {
        super.onResume();
        gameStart();
}


ここまでできたら実行してみましょう。
Time が1秒づつ減っていくと思います。


今日はここまで。次回に続く。


2014年3月22日土曜日

モグラ叩きゲームで学ぶアンドロイドプログラミング (3/8)

前回にひき続き、今回はいよいよモグラを登場させましょう。

まず、モグラの画像を res/drawable-hdpi/mole.png にコピーします。

次に、MainActivity.javaを修正していきます。
全体のソースコードは以下にあります。
https://gist.github.com/mrp1q7z/9705061

ボタンを保持する変数を定義します。(11行目)
縦5x横4の合計20個の配列として宣言します。
Button[][] mButton = new Button[5][4]; // [行][列]
ボタンを保持する変数に値をセットします。(18〜41行目)
mButton[0][0] = (Button) findViewById(R.id.Button1A);
mButton[0][1] = (Button) findViewById(R.id.Button1B);
mButton[0][2] = (Button) findViewById(R.id.Button1C);
・・・
mButton[4][3] = (Button) findViewById(R.id.Button5D);

モグラの画像を表示するメソッドを追加します。(71〜75行目)
行と列は乱数を発生させてランダムな場所に表示します。
private void printMole() {
  int row = (int) (Math.random() * 5);
  int col = (int) (Math.random() * 4);
  mButton[row][col].setBackgroundResource(R.drawable.mole);
}

上記メソッド(printMole)をアプリケーションの画面が表示された直後に
発生するイベント「onResume」で呼び出すようにします。(53〜57行目)
@Override
protected void onResume() {
  super.onResume();
  printMole();
}

ここまでできたら実行してみましょう。
ランダムに表示位置を変更しているので、画面を閉じて再度実行すると違う場所に表示されるはずです。


今日はここまで。次回に続く。

2014年3月14日金曜日

モグラ叩きゲームで学ぶアンドロイドプログラミング (2/8)

前回に続いて、今回も画面周りを作っていきましょう。

1.画像を追加

以下の画像を res/drawable-hdpi にコピーします。

モグラを叩いたときの手のマーク:btn_push.png
モグラの出てくる穴:hole.png

2.ボタンの背景画像を作成

モグラが出てくる部分はボタンにします。
そのボタンの背景画像を作成します。

res/drawable-nodpi/bg_button.xml というファイルを作成し、以下のように記述します。
※drawable-nodpi というフォルダがない場合は新規作成します。


<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- ボタンが押されている -->
    <!-- フォーカスされていない -->
    <item android:state_focused="false" android:state_pressed="true">
        <layer-list>
            <item android:drawable="@drawable/btn_push">
        </item></layer-list>
    </item>

    <!-- ボタンが押されていない -->
    <!-- フォーカスされていない -->
    <item android:state_focused="false" android:state_pressed="false">
        <layer-list>
            <item android:drawable="@drawable/hole">
        </item></layer-list>
    </item>

    <!-- ボタンが押されている -->
    <!-- フォーカスされた -->
    <item android:state_focused="true" android:state_pressed="true">
        <layer-list>
            <item android:drawable="@drawable/btn_push">
        </item></layer-list>
    </item>

    <!-- ボタンが押されていない -->
    <!-- フォーカスされた -->
    <item android:state_focused="true" android:state_pressed="false">
        <layer-list>
            <item android:drawable="@drawable/hole">
        </item></layer-list>
    </item>

</selector>

これは、ボタンが押されていないときは、モグラの穴を表示し、ボタンが押された時には手のマークを表示するように設定しています。

3.画面にボタンを配置する

縦に5つ、横に4つの格子状にボタンを配置します。
あと、上部にはスコアと、タイムの表示をします。
activity_main.xml を以下のように修正します。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bk_grass"
    tools:context="com.yojiokisoft.whacmole.app.MainActivity">

    <LinearLayout
        android:id="@+id/relativeLayout"
        android:layout_width="fill_parent"
        android:orientation="horizontal"
        android:paddingTop="20dp"
        android:paddingLeft="10dp"
        android:layout_height="60dp">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Score:"
            android:textSize="25sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="100"
            android:textSize="30sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Time:"
            android:textSize="25sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="60"
            android:textSize="30sp" />

    </LinearLayout>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="false"
        android:layout_below="@+id/relativeLayout">

        <TableLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true">

            <TableRow
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1">

                <Button
                    android:id="@+id/Button1A"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button1B"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button1C"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button1D"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

            </TableRow>

            <TableRow
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1">

                <Button
                    android:id="@+id/Button2A"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button2B"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button2C"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button2D"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

            </TableRow>

            <TableRow
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1">

                <Button
                    android:id="@+id/Button3A"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button3B"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button3C"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button3D"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

            </TableRow>

            <TableRow
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1">

                <Button
                    android:id="@+id/Button4A"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button4B"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button4C"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button4D"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

            </TableRow>

            <TableRow
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1">

                <Button
                    android:id="@+id/Button5A"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button5B"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button5C"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

                <Button
                    android:id="@+id/Button5D"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/bg_button" />

            </TableRow>
        </TableLayout>
    </RelativeLayout>

</RelativeLayout>


Button の背景には先ほど作成した bg_button を指定しています。

4.実行してみる


スコアやタイムは固定だし、モグラも出て来ませんが、モグラ叩きっぽくなりました。
ボタンを押すと、押した部分が手のマークになります。

今日は、ここまで。次回に続く。

モグラ叩きゲームで学ぶアンドロイドプログラミング (1/8)

アンドロイドプログラミングを始めようと思っている人に向けて
サンプルプログラムを作りながら学んでいくコーナーです。

ステップ、バイ、ステップで少しずつ開発していき、
最終的にモグラ叩きゲームの完成を目指します。

※開発環境は整っているという前提です。
※ここでは、Android Studio 0.5.1 を使います。


1.プロジェクトを作成

プロジェクト名は「WhacMole」にしました。



Blanck Activity を選択して、次へ


Activity Name は「MainActivity」にして、フィニッシュ。

2.背景画像を追加


drawable-hdpiに bk_grass.jpg を追加します。


activity_main.xml を開き、RelativeLayout の background に先ほど追加した
bk_grass を選択します。

3.実行してみる

背景画像が表示されました。

今日は、ここまで。次回に続く。