Androidアプリを作ってみる #21 -Surfaceview その4-

Surfaceviewになにか表示してみる

スレッドの中身にプログラミング

前回はSurfaceviewを使って絵を動かす部分を作りましたね。

前回の記事

Androidアプリを作ってみる #20 -Surfaceview その3-

2017.02.07

今回はいよいよそこに絵を描いてみたいと思います。

本Blogの内容を試して、トラブルや故障の原因になったとしても責任は負えません。そんな危ないことはしていませんが、自己責任でお願いしますね。

無限ループの停止条件を変える

前回ループを制御する部分を以下のように書いてましたけど(便宜上ローカル変数で宣言してます)、もしisLoopをfalseにし忘れると無限ループになりっぱなしになるバグの温床になってしまいます。

GameSurfaceview.java

なんかいい方法ないかなあと調べていたら、このSurfaceviewを作る時に宣言した「thread」のインスタンスがあるかどうかでループを制御させればいいということに落ち着きました。

こんな感じですね。nullは「存在しない」くらいの意味に捉えていて問題ないと思います。「!=」は「threadがnullじゃない時」という意味なので以下のループは「thread(インスタンス)が存在するときに実行」ということになります。

GameSurfaceview.java

インスタンスは、Wikiでは小難しいこと書いてますけど、ま、気にしなくていいです。基本newして宣言したものはインスタンスを持っているくらいの認識でいいかと。

オブジェクト指向言語においては、多くの場合クラスと呼ばれるものを元に作成したオブジェクトの実体を指す。

Wiki

にゃんこ
そんなんでいいのか!?

描画の開始終了を指示

じゃ早速描画させてみますか。っとここでSurfaceviewを使用するときのおまじないがあって、描画の開始と終了を指示しないといけないみたいです。

それがlockCanvas()とunlockCanvasAndPost()です。この中身が何かなんて気にすることはないです。開始と終了時に呼び出せばいいだけ。

この二つのメソッドはSurfaceholderのメソッドなのでが生成されるときに呼び出されるsurfaceCreated()で()内に書いてあるパラメータが渡されてくる「surfaceHolder」を保存しておきます。

()内に書いてあるパラメータ(引数)とか、メソッド内に宣言したものはメソッドの実行が終了すると消えてしまいます。

もう一つ、lockCanvas()を実行した時に描画するためのCanvasクラスのインスタンスが渡されるのでそれも保存します。この渡されたCanvasクラスに対して描画するものをどんどん入れていくイメージです。

A = Bとあった場合、等しいという意味ではなくBの値をAにコピーするという意味です。この場合は右辺がメソッドなのでメソッドが返す値をコピーするという意味になります。

GameSurfaceview.java

スポンサーリンク



Canvasで円を描いてみる

では、Canvasクラスを調べると色々ありますね。

じゃ円でも描いてみますか。円を描くのはdrawCircle()を使います。

drawCircle

Added in API level 1
void drawCircle (float cx, float cy, float radius, Paint paint)

Parameters
cx 描画位置X座標
cy 描画位置Y座標
radius 円の半径
paint 色とかを選べる

ふむふむ、Paintを使えば色とか指定できるわけね。とりあえず赤で塗りつぶす方法を調べてみる。

よし、これでできそう。こんな感じで書いてみてっと。

GameSurfaceview.java

で実行してみる。

あれ!?おかしい

出てきた画面はというと、あれ!?前と変わってない…。なんでだろ…。

失敗

前のと同じじゃん!?

って当たり前でした。Main部分を変えていないので新たに追加した描画プログラムの方が呼び出されていませんでした。

メリ
ひどいミスね

ここで前の背景を呼び出しているままで、しかもGamesurfaceviewを呼んでもいないという…。これじゃ変わらんわな。

MainActivity.java

ってことでここを直します。



新しく作ったクラスを使うために

まさに実体を作る

ここで、Surfaceviewを使うために用意したGameSurfaceviewのインスタンス(実体)化します。こうしてみました。

MainActivity.java

で実行。

android ミス

あれ!?真っ暗

は、はうっ。今度は真っ黒。

にゃんこ
ちゃんとやれって

こういう時はちゃんとドキュメント読みましょう。

なんかこの辺に書いてありました。Surfaceviewにちゃんとアクセスできていないっぽい。GameSurfaceviewのインスタンスを作った時に実行されるコンストラクタ「GameSurfaceview()」内にMainActivityとSurfaceviewを結びつけるものが何もないってことみたいです。

Access to the underlying surface is provided via the SurfaceHolder interface, which can be retrieved by calling getHolder().

[訳]

基底のサーフェスへのアクセスは、SurfaceHolderインタフェースを介して提供されます。このインタフェースは、getHolder()を呼び出して取得できます。

The Callback is set with SurfaceHolder.addCallback method.

[訳]

コールバックはSurfaceHolder.addCallbackメソッドで設定されます。

Android Developers Surfaceview SurfaceHolder.Callback

getHolder()でSurfaceとアクセスできるようにして、そこからsurfaceCreated()とかsurfaceDestroyed()とかが適切なタイミングで呼ばれるようにaddCallback()でセットするという流れ。最初にsurfaceCreated()でSurfaceHolderを保存したけど、それも要らないですね。どっからこの情報を持ってきたんだろ(疑問)。でそれを踏まえるとこうなります。

GameSurfaceview.java

凡ミス

で実行してみる…。それでもまたあの真っ黒画面です。何だろ〜と悩んでデバッグしていたところそもそもThread処理のrun()まで処理が来ていないことが判明。何でじゃーとまた悩みましたが、Threadを作るところでミスを発見。ここまででも出てきてますがGameSurfaceview自身を現す「this」を忘れてました。ThreadをGameSurfaceview上で実行すれ!って意味ですね。

GameSurfaceview.java

で実行!!

Android 表示

キターーー

これで目出度く赤丸を表示することに成功しました。意外に長い道のりでした…。次回はこれを動かしてみますかね。

メリ
表示だけで大変だったのに…。

次の記事

Androidアプリを作ってみる #22 -Surfaceview その5-

2017.05.03

前回の記事

Androidアプリを作ってみる #20 -Surfaceview その3-

2017.02.07

コメントを残す

メールアドレスが公開されることはありません。