質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

2295閲覧

AndroidStudio SurfaceViewのholder.lockCanvasについて

kirbyprog

総合スコア7

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2016/10/12 00:33

編集2016/10/13 08:31

###前提・実現したいこと
AndroidStudioを用いて簡単なアドベンチャーゲームを製作しようと思っています。
主な機能としてはまず、
1.タッチした方向に移動する(瞬間移動ではなく、少しずつ)
2.村人をタッチした場合、村人の近くまで移動し、会話する。
を実装したいと思っています。
教本を参考にしながら製作していたのですが、理解できないところがありましたので質問させていただきました。

###発生している問題
1.タッチした方向に移動する の方は、問題なく実装できているのですが
2.村人をタッチした場合、村人の近くまで移動し、会話する。 の方ができません。
具体的な症状ですが、主人公の移動はできるのですが、移動したあとなぜか他の方向へ瞬間移動した後村人との会話が成立してしまいます。
画像を参照にしていただけると幸いです。
瞬間移動する位置は、おそらく2フレーム前の位置になります。
可読性の悪いプログラムかと思いますが、ご助言のほどよろしくお願いします。
イメージ説明
###該当のソースコード

  • AdventureView.java

java

1public class AdventureView extends SurfaceView 2 implements SurfaceHolder.Callback,Runnable { 3 4 //変数の定義コーナー// 5 final static int W = 480, H = 800; 6 //シーン定数 7 private final static int sMAP = 0, sCHAT = 1; 8 private int key=0; 9 private final static int 10 KEY_NO_ACTION=0, 11 KEY_ACTION=1; 12 //システム 13 private SurfaceHolder holder; //サーフェイスホルダー 14 private Graphics g; 15 private Thread thread; //スレッド 16 private int scene; //シーン(1) 17 //BMP読み込み 18 private final static int num_bmp = 7;//読み込む画像の枚数 19 private Bitmap[] bmp = new Bitmap[num_bmp];//ビットマップ 20 private int[] image = {R.drawable.rpg0, R.drawable.rpg1, R.drawable.rpg2, R.drawable.rpg3, 21 R.drawable.rpg4, R.drawable.rpg5, R.drawable.rpg6}; 22 //MAP定数 23 private int[][] MAP = new int[10][10]; 24 //最初のところ(0:歩ける 1:人 3:壁(or物)) 25 private int[][]MAP_first = { 26 {3,3,3,3,3,3,3,3,3,3}, 27 {1,0,0,0,0,0,0,0,0,0}, 28 {1,0,0,0,0,0,0,0,0,0}, 29 {3,0,0,0,0,0,0,0,0,0}, 30 {3,0,0,0,0,1,0,0,0,0}, 31 {3,0,0,0,0,0,0,0,0,0}, 32 {3,0,0,0,3,0,0,0,0,3}, 33 {3,0,0,3,3,0,0,3,0,3}, 34 {3,3,3,3,3,3,3,3,3,3}, 35 {3,3,3,3,3,3,3,3,3,3}, 36 }; 37 //主人公の座標 38 private int myX; 39 private int myY; 40 //移動先の座標 41 private int Now_myX; 42 private int Now_myY; 43 //会話用 44 private String chat; 45 private int human; 46 private boolean FLAG_CHAT = false; 47 private int count_program = 0; 48 49 50 public AdventureView(Activity activity) { 51 super(activity); 52 53 //ビットマップファイルの読み込み 54 for (int i = 0; i < num_bmp; i++) { 55 bmp[i] = BitmapFactory.decodeResource(getResources(), image[i]); 56 } 57 //サーフェイスホルダーの生成 58 holder = getHolder(); 59 holder.addCallback(this); 60 //画面サイズの指定 61 Display display = activity.getWindowManager().getDefaultDisplay(); 62 Point p = new Point(); 63 display.getSize(p); 64 int dh = W * p.y / p.x; 65 //グラフィックスの生成 66 g = new Graphics(W, dh, holder);//surfaceHolderの生成等 67 g.setOrigin((dh - H) / 2, 0);//描画位置の設定 68 //変数の初期化 69 init(); 70 } 71 72 //サーフェイスの生成 73 public void surfaceCreated(SurfaceHolder holder) { 74 thread = new Thread(this); 75 thread.start(); 76 } 77 78 //サーフェイスの終了 79 public void surfaceDestroyed(SurfaceHolder holder) { 80 thread = null; 81 } 82 83 //サーフェイスの変更 84 public void surfaceChanged(SurfaceHolder holder, 85 int format, int w, int h) { 86 } 87 88 //スレッドの処理 89 public void run() { 90 while (thread != null) { 91 if (scene == sMAP) { 92 //移動 93 94 //描画 95 g.lock(); 96 //背景の描写 97 for (int i = 0; i < MAP[0].length; i++) { 98 for (int j = 0; j < MAP[0].length; j++) { 99 int idx = MAP[j][i]; 100 g.drawBitmap(bmp[idx], 48*i, 80*j,false); 101 } 102 } 103 //主人公移動用 104 //----------------------------------// 105 //x座標 106 int i = Now_myX - myX; 107 //y座標 108 int j = Now_myY - myY; 109 if (i == 0) { 110 if (j == 0) { 111 } else if (j < 0) { 112 Now_myY++; 113 } else { 114 Now_myY--; 115 } 116 } else if (i < 0) { 117 Now_myX++; 118 } else { 119 Now_myX--; 120 } 121 Log.d("run:sMAP","Through"+"Now_myX="+Now_myX+"myX="+myX 122 +"Now_myY="+Now_myY+"myY="+myY); 123 g.drawBitmap(bmp[4], Now_myX * 48, Now_myY * 80, true); 124 g.unlock(); 125 126 127 //会話する条件がそろったとき(=人をタッチしたかつ、人の近くまで移動したとき)実行 128 if(human != 0 && Now_myX==myX && Now_myY==myY){ 129 scene = sCHAT; 130 Log.d("会話条件TRUE","Through"); 131 } 132 //---------------------------------// 133 } 134 else if(scene == sCHAT){ 135 //ここから 136 Log.d("run:sChat", "Through"); 137 g.lock();// 138 m_chat(); 139 g.unlock(); 140 waitSelect(); 141 //ここまでが怪しい 142 //m_chat();を消しても効果なし。全部消すと会話文こそなくなるものの正常に動作する。 143 } 144 try { 145 Thread.sleep(300); 146 } catch (Exception e) { 147 } 148 } 149 } 150 151 @Override 152 public boolean onTouchEvent(MotionEvent event) { 153 int touchX = (int) (event.getX() * W / getWidth()); 154 int touchY = (int) (event.getY() * H / getHeight()); 155 int touchAction = event.getAction(); 156 switch (touchAction) { 157 case MotionEvent.ACTION_DOWN: 158 Log.d("ACTION_DOWN","Through"); 159 switch (scene) { 160 case sMAP: 161 Log.d("ACTION_DOWN:sMAP", "Through"); 162 //会話していないかつ、 163 //タッチした場所が人だった場合、変数human=1 164 //タッチした場所が動ける場所だった時、動く。 165 toTouch_Event(touchX, touchY); 166 break;//scene=sMAP 167 case sCHAT: 168 Log.d("ACTION_DOWN:sCHAT", "Through"); 169 scene = sMAP; 170 human = 0; 171 //とりあえず、会話画面が表示されて画面をタッチしたらまた移動できるように。 172 key = KEY_ACTION; 173 break;//scene=sCHAT 174 } 175 break;//actionEvent=down 176 } 177 return true; 178 } 179 //スリープ 180 private void sleep(int time) { 181 try { 182 Thread.sleep(time); 183 } catch (Exception e) { 184 } 185 } 186 //決定キー待ち 187 private void waitSelect(){ 188 key = KEY_NO_ACTION; 189 while(key!=KEY_ACTION){ 190 sleep(200); 191 } 192 } 193 //初期化 194 private void init(){ 195 MAP = MAP_first; 196 myX =2; 197 myY =2; 198 199 Now_myX=myX; 200 Now_myY=myY; 201 } 202 //主人公の移動 203 private void mMove(int x,int y){ 204 myX = x/48; 205 myY = y/80; 206 } 207 //MAPの状態 208 private int stateMAP(int x,int y){ 209 int state = 0; 210 int ax=x/48; 211 int ay=y/80; 212 state=MAP[ay][ax]; 213 return state; 214 } 215 //会話するため 216 private void m_chat(){ 217 chat = decision_chat(); 218 g.drawText(chat); 219 } 220 //会話の内容を決める。 221 private String decision_chat(){ 222 String string_chat; 223 string_chat = "テスト用会話:"+human; 224 return string_chat; 225 } 226 //タッチ先イベント処理 227 private void toTouch_Event(int e_touchX,int e_touchY){ 228 switch (stateMAP(e_touchX, e_touchY)) { 229 case 0: 230 mMove(e_touchX, e_touchY); 231 break;//scene=sMAP : stateMAP=case0 232 case 1: 233 if (stateMAP(e_touchX - 48, e_touchY - 80) == 0) { 234 myX = e_touchX - 48; 235 myY = e_touchY - 80; 236 mMove(myX, myY); 237 human = stateMAP(e_touchX, e_touchY); 238 } 239 break;//scene=sMAP: stateMAP=case1 240 } 241 } 242} 243 244```###試したこと 245ソースコード中に書いてある、あやしいと書いてあるところを変更することで仕様通りにはなりませんが、正常に動作しました。 246瞬間移動する際、主人公が移動するメソッドは使用されていませんでした。 247他の方法でも(テキストを表示させる)試してみたのですが、setTextメソッドを使わずに意図しない文章が表示されたのでおそらく何らかの形で画像が保存されて出力されているのかなと思いました。 248 249戻るのは、毎回2フレーム戻りました。 250また、村人の近くに行くのは1フレームのみでした。 251(タッチ→数フレーム→村人の近くへ→1フレーム→2フレーム前に戻る) 252###追記(10/13) 253```java 254~省略~ 255public boolean onTouchEvent(MotionEvent event) { 256 int touchAction = event.getAction(); 257 switch (touchAction) { 258 case MotionEvent.ACTION_DOWN: 259 switch (scene) { 260 case sMAP: 261 //タッチ先が人ならhuman=1にする。 262 toTouch_Event(touchX,touchY); 263 break;//scene=sMAP 264 case sCHAT: 265 Log.d("sCHAT", "Through"); 266 key = KEY_ACTION; 267 break;//scene=sCHAT 268 } 269 break;//actionEvent=down 270 } 271 return true; 272 } 273~省略~ 274**run()** 275else if(scene == sCHAT){ 276 FLAG_CHAT = true; 277 while(FLAG_CHAT==true){//falseにならないので無限ループに入る 278 g.lock(); 279 g.unlock(); 280 waitSelect();//タッチすると1フレーム動く 281 } 282

一部を上記のように書き直した際、主人公の位置は、
2フレーム前→1フレーム前→0フレーム前→2フレーム前→1フレーム前→・・・
と繰り返して位置が変わっていました。
この時の変数は、常に一定の値で予期していた値通りでした。
また、Bitmapを描写する関数を通ったLOGも見られませんでした。

###追記2(10/13)
イメージ説明
イメージ説明
イメージ説明
また、ソースコードの変更も行いましたので、更新させていただきます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

SurfaceViewが意図せず描画を保存しておくことはないと思います。
myX,myY,Now_myX,Now_myYをログ出力して想定と異なる変化をしていないかを確認してください。
この4つの更新処理が怪しいと思います。

投稿2016/10/12 01:16

yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kirbyprog

2016/10/12 04:32

解答ありがとうございます。 Loggを用いて、変数を調べたのですが、画像を描写するメソッド(drawBitmap)の前では意図しない値への変更はありませんでした。 ここには書いてありませんが、タッチしたら次の会話が出てくるようにしたときも、同様に最後の会話がでてから2フレーム前の描写に戻ってしまいました。このときもテキストを書くメソッドは、戻ったときだけ通っていませんでした。
yona

2016/10/12 05:33

つまり、sCHAT状態になってからは座標は変化していないということですね?
yona

2016/10/12 05:34

あと、sCHAT状態でタッチした場合にフィールド変数が変化しそうですがこれは大丈夫ですか?
kirbyprog

2016/10/12 17:39

遅くなりすみません。 sCHAT状態ならば座標は変化していないということです。 >>あと、sCHAT状態でタッチした場合にフィールド変数が変化しそうですがこれは大丈夫ですか? 書いてあるプログラムは、 人をタッチすると、 ①人の近くまで行く。 ②会話文が表示される。 ③さらにそこから画面をタッチすると会話文が消える。 ④sMAP状態(マップ上を動ける状態に) といった機能を実装したいので大丈夫だと思います。
yona

2016/10/13 01:56

タッチするとsceneにsMAPが入りますよね?これは大丈夫なんですか? また、瞬間移動先は毎回同じですか?
kirbyprog

2016/10/13 02:06

タッチしてsceneにsMAPが入らないプログラム(追記を参照してくださいると幸いです)も製作したのですが、症状に変化は見られませんでした。 瞬間移動先は、村人をタッチするときの主人公の位置によって変わります。 正確には、主人公が村人まで移動した道のりにより、決まり、村人につく2フレーム前の位置に瞬間移動するみたいです。
yona

2016/10/13 03:57

混乱してきましたね。今までのやりとりは少し置いておきましょう。 ログをベースに話しましょう。下記のログを取ってください。 ・MotionEvent.ACTION_DOWN直後のログ ・myX,myY,Now_myX,Now_myYの変化がわかるログ ・sceneがsCHATに変わったタイミングのログ ・会話を進めるタッチが起こったログ ・sceneがsMAPに変わったタイミングのログ
kirbyprog

2016/10/13 08:15

助言していただきありがとうございます。。 助言通り、LOGをとってみましたので追記を参照していただき、コメントいただけると助かります。
yona

2016/10/13 12:53

ログありがとうござます。 値は正常になっていますね。 ふと思ったんですが、会話状態であってもマップや主人公、村人なども描画しないといけなかったと思いますが、どうですか?
kirbyprog

2016/10/13 13:16

確かにそうですね、、、 今調べたら、surfaceviewは、すべて消してから描画でなくて前の状態を残して描画するんですね..。怪しい(..) 試しに会話状態で、主人公を(4,3)に書いたところ分裂しました。
yona

2016/10/13 13:18

書籍には一度Canvasの内容を削除しろとか書いてありませんか?
kirbyprog

2016/10/13 13:51

Canvasを消去するようなことは、書いてないです。 書籍では、主人公は移動せず(背景が動く)、会話も起きないのですが、 Viewを継承しているクラスで使われるようなキャンパスを消去するメソッドも使われていませんでした。
yona

2016/10/13 13:54

では、背景等を描画する処理はどうでしょうか?
kirbyprog

2016/10/13 14:27 編集

書籍は、移動→バトル画面へといった処理を行っているのですが、その時どちらの画面でも表示されるテキストは移動の時のみ描写されています。 訂正: すみません。関数中に入っていて見逃していましたがバトル画面でも描写されていました。
kirbyprog

2016/10/13 14:31

村人との会話中のcanva.lock状態でマップの描写と主人公の位置の描写全部書くことで正常に動作することが出来ました!!! 助言していただき、ありがとうございました(._.)
yona

2016/10/13 14:38

フレームが戻っていたではなく、フレームが残っていたが正しそうですね。
kirbyprog

2016/10/13 15:00

その通りのようです。 本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問