feature image

2016年5月20日 | 活動紹介

Android講習会

どうも、Namazuです。
この記事はAndroid講習会の資料となります。
なお、この講習会でソースコードの資料としてgitLabの方にAndroidLectureApp(本記事のLectureApp)とGravityGameが上がっています。
そちらもお役立てください。

1.講習会担当者紹介

2.Android開発の利点

3.開発の準備 <Android Studio導入、新規プロジェクト作成>

Android Studioの導入

以下のページからAndroid StudioをDLしてください。
http://developer.android.com/intl/ja/sdk/index.html
Android Studioは現在公式で推奨されているAndroidアプリの開発環境です。
以前はEclipseを用いた開発も行われていましたが、今はこちらが主流のようです。
今回はAndroid Studioを用いて開発を行います。

起動するとJDKのインストールが求められますので青文字のリンクから飛んで
自分のPCに合うバージョンのJDKをDLしてください。
一度実行したのちAndroidStudioの方で[Next]を押して進めてください。

新規プロジェクト作成

[File]→[New]→[New Project]を選択し、「LectureApp」と名前を付けてください。
その後[Next]、バージョンはAndroid 4.2(API Level 17)にしてください。
その後[Next]、テンプレートは[Empty Activity]を選択してください。次のページに進み、そのまま[Finish]を押すとプロジェクトの構築が始まります。

4.通過儀礼~Hello,World~ <プロジェクトの実行>

それではAndroidをお持ちの方は早速繋いで、そうでない方も▶をクリックし、実行してみましょう。[Device Chooser]のウィンドウが開きます。
ここでAndroidを持っている方は上のボックスに自分のAndroidが読み込まれて表示されると思います。それを選択して[OK]を押してください。
お持ちでない方は下の[Launch Emulator]を選択し、[none]と書かれた右側の[…]から新しく仮装デバイスを設定します。
[Create Virtual Device]
→[Phone][Galaxy Nexus , xxhdpi]→[Next]
→[Show downloadable system images][JellyBean , API Level17 , ABI x86]→[Next]
→[Finish]
と設定してください。設定出来たらAndroid Virtual Device Managerを閉じて、[Device Chooser]で設定した仮装デバイスが選択されていることを確認して[OK]を押してください。

実は、デフォルトでHello,Worldが書かれているので実行すると「Hello,World」と表示されます。

5.文字とレイアウト <TextView,レイアウトファイル>

まずはAndroidアプリ開発の基本としてTextViewに触れましょう。
これは文字の表示をするためのクラスです。ただのString型とは違います。
activity_main.xmlを開くと、中に以下のような記述があると思います。
activity_main.xml


<TextView
android:text="Hello,World"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

これこそ、Hello,Worldを表示させていたものの正体です。
では、早速少し変えてみましょう。以下のように書き換えてください。
activity_main.xml


<TextView
android:id="@+id/text"
android:text="Hello World!"
android:textSize="40sp"
android:textColor="#ff0088"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

実行すると、文字が大きくなり色も赤くなったと思います。
テキストのデフォルトの色やサイズなどを設定したいときはこのように記述してください。
さて、ここで"デフォルト"と言ったのには理由がありまして、それはプログラムの方で書き換えることが出来るからです。
MainActivity.javaの該当部分を以下のように書き換えてください。
MainActivity.java


public class MainActivity extends AppCompatActivity {
private TextView text;//①
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.text);//②
text.setText("Po");//③
}
}

実行してみると、テキストの内容が"Po"になっています。
簡単に流れを説明しますと、
①:TextViewクラスの参照型変数textを作成
②:TextViewクラスのインスタンス:text(activity_mainで作成したもの)を代入
③:textの表示内容を"Po"に変更
という感じになります。

ちなみに、ですが以下のように記述するとjavaだけでレイアウトを記述することもできます。
MainActivity.java


public class MainActivity extends AppCompatActivity {

private TextView text;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout r = new RelativeLayout(this);
text = new TextView(this);
text.setText("Po");
text.setTextSize(40);
text.setTextColor(Color.RED);
r.addView(text);
setContentView(r);
}
}

こちらの方が分かりやすいという方もいらっしゃいますが、プロジェクトの規模が大きくなってくるとプログラムの内容とレイアウトの内容を別のファイルに分けた方が分かりやすくなります。
(レイアウトを全てjavaに書いてしまったのもインターンチャレンジ失敗の一つの要因だったようです)
今回の講習会ではそこまで大事ではありませんが、Androidで何かを開発しようとした時に必要になってくると思うので一応頭にとどめておいてください。

検索用キーワード:
TextView ImageView Button CheckBox Spinner...
RelativeLayout LinearLayout TableLayout...

5.自分だけのViewを作ろう

ここでは、クラス・コンストラクタ・継承の知識が少し必要になります。
<簡単に説明>

classSamidare

さて、新しくViewを作るにはまずViewのクラスを用意します。
画面左のProject ViewのMainActivityを右クリックして、[New]→[Java Class]を選択し、名前を「LectureView.java」にします。
まず、該当部分に以下のコードを記述してください。

LectureView.java


public class LectureView extends View {

public LectureView(Context context) {
super(context);
}

@Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
}
}

MainActivity.java


public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LectureView lectureView = new LectureView(this);
setContentView(lectureView);
}
}

これは新しいViewを作成するときの基本形です。
コンストラクタの作成とonDrawメソッドのオーバーライドをこのように行います。
ともに、superクラス(Viewクラス)のメソッドを始めに実行することでViewとしての体裁と整えてくれます。
onDrawメソッドは文字通り描画処理用のメソッドです。
onDrawメソッドの最後にinvalidate();と記述すると毎フレーム実行し直してくれるので繰り返し処理をここに書くこともできます。

さて、今回はGravityGameに入る前に何かしら動くものを作ってみましょう。
まずは新しくMainActivityと同じフォルダにLissajous.javaを作成します。

Lissajous.java


public class Lissajous {
private final Paint paint = new Paint();
private final int range;
private final int circleRange;


public Lissajous(){
this.range = 200;
this.circleRange = 20;
}

public void draw(Canvas canvas,double arg){
int x = canvas.getWidth()/2;
int y = canvas.getHeight()/2;
double centerX = x + range * Math.cos(4*arg);
double centerY = y + range * Math.sin(5*arg);
paint.setColor(Color.GREEN);
canvas.drawCircle((float)centerX,(float)centerY,circleRange,paint);
}
}

これはリサージュ曲線の軌道にそって動く緑色の円のオブジェクトのクラスです。
クラスの中にオブジェクトの描画処理も書いておきます。
今回は分離しましたが、オブジェクトが数種類ある場合などはクラス内に移動処理も書いておくと便利です。
さて、それではこれを描画してみましょう。

LectureView.java


public class LectureView extends View {

private Lissajous lissajous;
private double arg = 0.0;

public LectureView(Context context) {
super(context);
lissajous = new Lissajous();

}

@Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
lissajous.draw(canvas,arg);
arg += 0.01;
invalidate();
}

}

このように、LectureViewでLissajousのインスタンスを作成し、描画処理を書くことでインスタンスの描画が画面に反映されます。
ついでにオブジェクトの扱い方の練習のためにインスタンスを複数作成してみましょう。

LectureView.java


public class LectureView extends View {

private Lissajous[] lissajous = new Lissajous[10];

private double arg = 0.0;

public LectureView(Context context) {
super(context);
for(int i=0;i&lt;10;i++){
lissajous[i] = new Lissajous();
}
}

@Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
for(int i=0;i&lt;10;i++){
lissajous[i].draw(canvas, arg+i*Math.PI/5);
}
arg += 0.01;
invalidate();
}
}

Lissajousの配列を用いることで10個のインスタンスを作成しています。
このように、クラスを一つ作っておくだけで複数のオブジェクトを簡単に作ることができます。

6.SurfaceViewを使おう

さて、これまでViewを継承してLectureViewを作ってきましたが、実はこれには問題があります。
Viewは処理をメインスレッドで実行してしまうので、重い描画処理をしようとした時にカクカクしてしまうのです。
そこで、別スレッドで描画処理を行うような仕組みを活用したいと思います。
それがSurfaceViewです。
LectureViewを以下のように書き換えてください。コピペで構いません。

LectureView.java


public class LectureView extends SurfaceView implements SurfaceHolder.Callback{

private final long DRAW_INTERVAL = 1000 / 100;

private class DrawThread extends Thread {
private final AtomicBoolean isFinished = new AtomicBoolean(false);
public void finish(){
isFinished.set(true);
}
@Override
public void run() {
SurfaceHolder holder = getHolder();
while(!isFinished.get()) {
if(holder.isCreating()){
continue;
}
Canvas canvas = holder.lockCanvas();
if(canvas == null){
continue;
}

drawView(canvas);

holder.unlockCanvasAndPost(canvas);
synchronized (this){
try {
wait(DRAW_INTERVAL);
} catch (InterruptedException e) {
}
}
}
}
}

private DrawThread drawThread;

public void startDrawThread(){
stopDrawThread();
drawThread = new DrawThread();
drawThread.start();
}
public boolean stopDrawThread() {
if(drawThread == null){
return false;
}
drawThread.finish();
drawThread = null;

return true;
}
@Override
public void surfaceCreated(SurfaceHolder holder){
}
@Override
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){
startDrawThread();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder){
stopDrawThread();
}

private Lissajous[] lissajous = new Lissajous[10];

private double arg = 0.0;

public LectureView(Context context) {
super(context);
for(int i=0;i&lt;10;i++){
lissajous[i] = new Lissajous();
}
getHolder().addCallback(this);
}

public void drawView(Canvas canvas){
canvas.drawColor(Color.WHITE);
for(int i=0;i&lt;10;i++){
lissajous[i].draw(canvas, arg+i*Math.PI/5);
}
arg += 0.01;
}
}

変更された主な点は以下の通りです。

要するにおまじないだと思ってください。
ゲームを作成するときは基本的にSurfaceViewが使われます。
自分で何か作ろうとした場合もほとんど上記のコピペで構いません。

追記:
gitの方にLectureAppを拡張したものを上げておきました。
defaultはここで作成した最後の状態です。
係数の変更(タッチイベントの取得)、軌道の表示/非表示の切り替え等ができるようになっています。

Namazu icon
この記事を書いた人
Namazu

Namazuです。 今まで制作に携わったゲームはTypingWar、EccentricEscape、進捗どうですか?、NinjaFlicker等です。 MonoGameにまつわる記事も書いています。

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

ERC20トークンを用いた宝探しゲーム(真)の提案【アドベントカレンダー2018 10日目】 feature image
2018年11月3日
ERC20トークンを用いた宝探しゲーム(真)の提案【アドベントカレンダー2018 10日目】
Azon icon Azon
2022年4月7日
traPグラフィック班の活動紹介
annin icon annin
2021年8月12日
CPCTFを支えたWebshell
mazrean icon mazrean
2021年5月19日
CPCTF2021を実現させたスコアサーバー
xxpoxx icon xxpoxx
2021年3月19日
traPグラフィック班の活動紹介
NABE icon NABE
2023年4月27日
Vulkanのデバイスドライバを自作してみた
kegra icon kegra
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記